遇见问题
在反序列化的时候,我们可能会遇到这样的代码
<?php
class Flag {
public function flag(){
echo "Hello World !";
}
}
class Healper {
public $function;
public $name;
public function __destruct()
{
$this->function[$this->name]();
}
}
serialize($_POST['a']);
分析问题
这是一个一看就很简单的PHP反序列化,构造思路就是利用 Healper 的 __destruct()
去构造 Flag→flag()
的动态函数。
但是这里的$this→function[$this→name]()
只能访问 $function 中的一个参数
提出解决方案一(错误方案)
假设我们构造如下的代码
<?php
class Flag {
public function flag(){
echo "Hello World !";
}
}
class Healper {
public $function;
public $name;
public function __destruct()
{
$this->function[$this->name]();
}
}
$a = new Healper();
$a -> function = new Flag();
$a -> name = "flag";
这串代码看样子可以执行
实际却是这样

$function 是一个对象,而这个对象中没有 flag 这个参数,因为 flag 是方法,没有数据,所以flag也就不会存在于 Flag 对象的内存空间中
执行结果就是

提出解决方案二(正确方案)
经过学长的点拨,我发现可以让 $function[$name] 成为一个包含对象和方法名的数组,而这个数组就可以表示 $Flag→flag()
代码
<?php
class Flag {
public function flag(){
echo "Hello World !";
}
}
class Healper {
public $function;
public $name;
public function __destruct()
{
$this->function[$this->name]();
}
}
$a = new Healper();
$b = new flag();
$a -> function = ["ff"=>[$b, "flag"]];
$a -> name = "ff";
执行过程

这里的 $this→function[$this→name]
这一大串就是数组 ff
,这一行等效于 ff()
; ff是数组
执行结果

总结
当需要使用动态函数的功能执行某个对象中的方法的时候,只需要让这个动态函数成为一个包含对象和对象方法名的数组即可

下面的 [$a, “flag”]()
等效于 $a → flag()