easy_serialize_php

source_code:

<?php
// 提交$f参数
$function = @$_GET['f'];
// 过滤函数$img 将关键字替换为""
function filter($img)
{
    $filter_arr = array('php', 'flag', 'php5', 'php4', 'fl1g');
    $filter = '/' . implode('|', $filter_arr) . '/i';
    return preg_replace($filter, '', $img);
}


if ($_SESSION) {
    unset($_SESSION);
}

$_SESSION["user"] = 'guest';
$_SESSION['function'] = $function;
// 支持POST传参
extract($_POST);

if (!$function) {
    echo '<a href="index.php?f=highlight_file">source_code</a>';
}

// 先对图片数据进行编码
if (!$_GET['img_path']) {
    $_SESSION['img'] = base64_encode('guest_img.png');
} else {
    $_SESSION['img'] = sha1(base64_encode($_GET['img_path']));
}

// 序列化后过滤函数
$serialize_info = filter(serialize($_SESSION));

// 反序列化后读取文件
if ($function == 'highlight_file') {
    highlight_file('index.php');
} else if ($function == 'phpinfo') {
    eval('phpinfo();'); //maybe you can find something in here!
} else if ($function == 'show_image') {
    $userinfo = unserialize($serialize_info);
    echo file_get_contents(base64_decode($userinfo['img']));
}

审计代码,查看phpinfo,可以看到存在疑似flag文件d0g3_f1ag.php。

接下来尝试的就是如何读取文件了。由于传入$img_path会被base64编码后哈希加密,所以无法通过该变量读取文件。

审计一下代码逻辑。首先程序支持POST方式传参。先将图片数据进行编码,序列化$_SESSION的值之后调用filter函数,将关键字通过空格代替。接着反序列化变量,base64解码decode变量。

这边有一个比较明显的漏洞就是先调用序列化再执行filter函数,导致反序列化字符串逃逸。

这里利用了值逃逸,参考

POST参数

_SESSION[user]=flagflagflagflagflagflag&_SESSION[function]=a";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";s:2:"dd";s:1:"a";}

然后改BASE64编码,长度一样。

Last updated