php代码审计之反序列化漏洞

目录

php反序列化

Phar反序列化概要

phar文件的结构:

原生类序列化

Session反序列化

Session反序列化的特殊利用


php反序列化

什么是反序列化?

序列化就是将一个对象转换成字符串。字符串包括 属性名 属性值 属性类型和该对象对应的类名。反序列化则相反将字符串重新恢复成对象


serialize()                序列化
unserialize()           反序列化

漏洞原理:
PHP将所有以__ (两个下划线)开头的类方法保留为魔术方法。所以在定义类方法时,除了上述魔术方法,建议不要以__为前缀。
常见的魔术方法:

  • __construct()当以个对象创建时被调用
  • __destruct()当一个对象销毁时被调用
  • __toString()当一个对象被当作一个字符串使用
  • __sleep() 在对象在被序列化之前运行
  • __wakeup将在序列化之后立即被调用

PHP类中的特殊属性
序列化为了能把整个类对象的各种信息完完整整的压缩,格式化,也会将属性的权限序列化进去。但不同类型的属性会有不同的格式
1. Public 权限
可以内部调用,实例调用等
2. Private权限                                                  ( test flag)反序列化时会多两个空字节00==>可以传递%00test%00flag进行反序列化
被private修饰的只能是同一个类的可以访问
3. Protected权限                                             ( * test)同样多了两个空字节==>%00*%00test进行反序列化
对继承的类开放,没继承的类不开放

 

Phar反序列化概要


除了unserialize()来利用反序列化漏洞之外,还可以利用phar文件以序列化的形式存储用户自定义的meta-data这一特性,扩大php反序列化漏洞的攻击面。该方法在文件系统函数(file__exists()、 is__dir()等)参数可控的情况下,配合phar://伪协议,可以不依赖unserialize()直接进行反序列化操作。
来自Secarma的安全研究员Sam Thomas发现了-种新的漏洞利用方式,可以在不使用php函数unserialize()的前提下,引起严重的php对象注入漏洞。这个新的攻击方式被他公开在了美国的BlackHat会议演讲上,演讲主题为:”不为人所知的php反序列化漏洞”。它可以使攻击者将相关漏洞的严重程度升级为远程代码执行。我们在RIPS代码分析引擎中添加了对这种新型攻击的检测。

因此可以构造一个恶意的phar包,使得代码能够被反序列化,在使用phar://协议读取文件时,文件会被机械成为phar,解析过程种会触发php_var_unserialize()函数对meta-data的操作,造成反序列化

什么是Phar文件?
在软件中,PHAR (PHP归档) 文件是一种打包格式,通过将许多PHP代码文件和其他资源(例如图像,样式表等)捆绑到一个归档文件中来实现应用程序和库的分发。php通过用户定义和内置的“流包装器”实现复杂的文件处理功能。内置包装器可用于文件系统函数,如(fopen(),copy(,file_exists()和filesize()。 phar://就是一 种内置的流包装器。

php中一些常见的流包装器如下:
file://        -访问本地文件系统,在用文件系统函数时默认就使用该包装器
大http://      -访问HTTP(s) 网址
ftp://         -访问FTP(s) URLS
php://         -访问各个输入/输出流(I/O streams)
zlib://        -压缩流
data://        -数据(RFC 2397)
glob://        -查找匹配的文件路径模式
phar://        -PHP归档
ssh2://        -Secure Shell 2
rar://         -RAR
ogg://         -音频流
expect://      -处理交互式的流

phar文件的结构:

Phar文件都包含以下几个部分

  1. stubphar               文件的标志,必须以xxx HALT_ COMPILER();?> 结尾,否则无法识别。 xxx可以为自定义内容。
  2. manifest                phar文件本质上是一种压缩文件,其中每个被压缩文件的权限、属性等信息都放在这部分。这部分还会以序列化的形式存储用户自定义的meta-data,这是漏洞利用最核心的地方。
  3.  content                被压缩文件的内容
  4. signature              (可空)签名,放在末尾。

php.ini中的phar.readonly选项设置为off

startBuffering();

	$phar->setStub(" "); //设置stub

        //$phar -> setStub('GIF89a'.'');   //增加gif头,绕过gif检测
	$o = new TestObject();

	$phar->setMetadata($o); //将自定义的meta-data存入manifest

	$phar->addFromString("test.txt", "
		test"); //添加要压缩的文件
	//签名自动计算
	$phar->stopBuffering();
?>

 

php代码审计之反序列化漏洞_第1张图片

 

实际在文件上传的时候,如果存在利用条件,可以将生成的phar.phar文件后缀更改为phar.gif上传

php代码审计之反序列化漏洞_第2张图片

php一大部分文件系统函数在通过phar://伪协议解析phar文件时,都会将meta-data进行反序列化受影响函数的链接

 

Phar反序列化漏洞的利用条件:

  1. phar文件要能够上传到服务器端。
  2. 要有可用的魔术方法作为“跳板”。
  3. 文件操作函数的参数可控,且:、/、phar等特殊字符没有被过滤。

 

原生类序列化

  • 原生类同名函数

SessionHandler::open()
当$flag=ZipArchive:OVERWRITE时,就会将$filename的文件删除

open('1.txt', ZipArchive:OVERWRITE)
?>

 

  • 原生类魔法函数

public SoapClient::SoapClient ( mixed $wsdI [, array $options ] )
第一个参数是用来指明是否是wsdl模式,如果为null,那就是非wsdl模式,反序列化的时候会对第二个参数指明的url进行soap请求。

SOAP是webService三要素(SOAP 、WSDL(WebServicesDescriptionl anguage)、
UDDI(UniversalDescriptionDiscovery. andIntegration))之一
WSDL用来描述如何访问具体的接口
UDDI用来管理,分发,查询webService
SOAP(简单对象访问协议)是连接或Web服务或客户端和Web服务之间的接口。
webService相当于HTTP + XML

 

Session反序列化

PHP中的session保存:PHP.ini有以下配置项用于控制session有关的设置:
 

session.save_path="D:lxampp\tmp"                                      表明所有的session文件都是存储在xampp/tmp下
session.save_handler = files                                          表明session是以文件的方式来进行存储的
session.auto start=0                                                  表明默认不启动session
session.serialize_handler= php                                        表明session的默认序列话引擎使用的是php序列化引擎




设置session为$_ SESSION["name"] = "Threezh1";时。不同的引擎保存的session文件内容如下:

php:
    name|s:8:"Threezh1";
    存储方式是,键名+竖线+经过serialize()函数序列处理的值


php.binary:
    names:8:"Threezh1";
    存储方式是,键名的长度对应的ASCII字符+键名+经过serialize()函数序列化处理的值    

php.serialize(php>5.5.4):
    a:1:{s:4:"name' ;:8:"Threezh1";}
    存储方式是经过serialize()函 数序列化处理的值

 

Session反序列化的特殊利用


当PHP中sessionupload progress enabled打开时,php会记录上传文件的进度,在上传时会将其信息保存在$_SESSION中。

  1. sessionupload progress.enabled= On (是否启用上传进度报告)
  2. sessionupload progress.cleanup= Off (是否上传完成之后删除session文件)

上传文件进度的报告就会以写入到session文件中,所以我们可以设置-一个与session.upload progress.name同名的变量(默认名为PHP_SESSION_UPLOAD_PROGRESS),PHP检测到这种同名请求会在$_SESSION中添加一条数据。我们就可以控制这个数据内容为我们的恶意payload。

mdzz = 'phpinfo();';
    }
    
    function __destruct()
    {
        eval($this->mdzz);
    }
}
if(isset($_GET['phpinfo']))
{
    $m = new OowoO();
}
else
{
    highlight_string(file_get_contents('index.php'));
}
?>

exp.php

mdzz = "print_r(scandir(__dir__));";
echo serialize($a);
//生成序列化payload
  
?>

php代码审计之反序列化漏洞_第3张图片

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(PHP代码审计)