首先看有危害的地方,如:eval,assert,system,include等危险函数,本题有危害的地方是
public function append($value){
include($value);
}
这里界说了一个参数可以包罗文件,而本题开头也有提示,flag在flag.php里面。
那么接下来找哪里调用了这个方法
public function __invoke(){
$this->append($this->var);
}
可以看到invoke()这个魔术方法调用了append方法,那么怎样触发(当对象被当作函数触发时)也就是类名加上(),
找下一环怎么才气让对象被当作函数触发
class Test{
public $p;
public function __construct(){
$this->p = array();
}
public function __get($key){
$function = $this->p;
return $function();
}
}
这里最后如果把p传入一个append的对象Modifier,那么最后会返回Modifier(), __construct()(这个方法创建对象大概实例化对象就触发不用理它),那么偏重看__get(),这个要调用一个不存在的成员变量来触发,那么下一步就是去找怎样才气调用不存在的成员变量
public function __toString(){
return $this->str->source;
}
这里的意思是如果触发__toString(),那么返回str里的source属性,先不用管它为什么同为属性,str就能调用source,这里把它当成了一个对象,那么如果给str赋一个没有source的对象,这不就有不存在的成员变量了嘛,那么可以给str赋值为Test来触发__get方法。这个__toString()的触发方式是把对象当成字符串:
__toString() //当反序列化后的对象被输出在模板中的时候(转换成字符串的时候)主动调用(用echo输出对象的时候会触发)(php中echo 只能输出字符串,而print_r()可以输出对象,数组等)
来找一个有echo且能赋值的地方
public function __construct($file='index.php'){
$this->source = $file;
echo 'Welcome to '.$this->source."<br>";
}
这里就能赋值的同时用echo输出,那么给source赋值一个对象就行了,其他两个类都用了,这次就只能用它本身的类Show了,这里是__construct()方法就不用想办法让它触发了,那么一个pop链就完成了,这里我用的是倒推法
__construct-> __toString()->__get()->__invoke()-> append($value)(触发文件包罗)
那么就把这些序列化吧,