PHP反序列化漏洞的新攻击面

作者:网友投稿 时间:2018-08-30 16:26

字号

自从2009年Stefan Essar提出PHP反序列化问题以来,已经有大量的CVE出现,例如CVE-2017-12934、CVE-2017-12933等。今年8月份的美国blackhat上Sam Thomas提出了一种新的反序列化攻击场景,而且这种场景可能伴随着xxe、ssrf或者其他相关漏洞的出现而出现。本文将会对此进行介绍,并针对wordpress中的漏洞进行复现。

二、 PHP反序列化漏洞 2.1 漏洞简介

php反序列化漏洞也叫PHP对象注入,形成原因为程序未对用户输入的序列化字符串进行检测,导致攻击者可以控制反序列化过程,从而导致代码执行、文件操作、执行数据库操作等不可控后果。这一类攻击在java、python等面向对象语言中均存在。

2.2 漏洞主要原理

在大型web项目中可能存在如下代码:

<?php class AnyClass {     public $name; function __destruct() { passthru($this->name); } }

在AnyClass类中,存在一个变量$name,同时也存在一个destruct方法。在__destruct方法中调用了passthru函数,而这个函数的参数恰好是成员变量$name。__destruct这一类成员方法会在某些特定情况下自动调用,例如当类的实例被销毁时就会调用__destruct。这一类的方法被统称为magic方法,还包括__construct、__toString等。

php允许保存一个对象方便以后重用,这个过程被称为序列化。serialize函数会将一个对象的名字和他的成员变量的值保存起来,而unserialize函数则反其道而行之将对象还原,在这一过程中对象的成员变量将保留,而成员函数信息则不会存储。例如:

<?php …… $obj = new AnyClass(); $obj->name = “test”; $res = serialize($obj); echo $res; var_dump(unserialize($res));

将首先会输出O:8:”AnyClass”:1:{s:4:”name”;s:4:”test”;},然后反序列化还原后为:

1.png

1.png

而当脚本执行结束时,对象将会被销毁,此时会调用__destruct函数,如果我们将name变量设置为whoami,则将会执行系统命令:

internal\xxxx

因此当我们可以控制unserialize函数的输入,同时在服务端代码中存在一个类满足以下条件:

包含一个魔术方法,例如__destruct

魔术方法中直接或者间接存在危险函数,例如eval、call_user_func等

能够通过设置成员变量控制危险函数参数

如果成员$name属性不为public,则需要通过成员函数进行修改,而如果为protected,我们还可以通过新建一个子类,然后在子类中进行赋值和序列化,例如:

class ChildClass extends AnyClass{ protected $wc; public function make(){ $this->wc = new AnyClass(); $this->wc->name = 'whoami'; return serialize($this->wc); } }

此时序列化内容为:O:8:”AnyClass”:1:{s:7:”*name”;s:6:”whoami”;},其中name部分有7个字节是因为还包含两个ascall码为0的不可见字符,二进制为%00*%00,这是为了标识protected和private变量。因此如果存在protected变量,序列化的内容必须通过二进制方式传入或者进行base64编码。

最终传入的序列化内容被反序列化时,将导致远程命令执行。

三、流转换器(Stream Wrappers)

PHP的文件操作函数,例如fopen()、copy()、file_exists()、filesize()等函数能够接受许多内置的流转换器,php 5.3以后的主要流转换器包括:

file://

ftp://

php://

zlib://

data://

glob://

phar://

“php://”目前在xxe、本地文件包含或者SSRF等漏洞经常被用到,例如php://input,同时还能通过“php://filter/convert.base64- encode/resource=index.php”来读写文件。“ftp://”、“data://”、“”则可用于远程文件包含,而在之前”phar://”则很少引起注意。

3.1 phar流转换器

根据php官方手册,phar类似于java的jar归档格式,但它可直接由php本身创建和使用,因此相当灵活。”phar://”则允许我们将多个文件归入一个本地文件夹。

创建一个phar文件十分简单:

@unlink("phar.phar"); $phar = new Phar("phar.phar"); $phar->startBuffering(); $phar->addFromString("test.txt","test"); $phar->setStub("<?php __HALT_COMPILER(); ?>"); $phar->setMetadata($this->wc); $phar->stopBuffering();

通过setMetadata可以将对象以序列化的形式存入phar文件中:

2.png

2.png

当metadata通过setMetadata存储后,解析时,php内核中会调用phar_parse_metadata函数:

责任编辑:CQITer新闻报料:400-888-8888   本站原创,未经授权不得转载
继续阅读
热新闻
推荐
关于我们联系我们免责声明隐私政策 友情链接