[HarekazeCTF2019]encode_and_encode
感觉是一个外国比赛的签到题,思路很清楚就是不知道怎么实现
题目给了源码
<?php
error_reporting(0);
if (isset($_GET['source'])) {
show_source(__FILE__);
exit();
}
function is_valid($str) {
$banword = [
// no path traversal
'\.\.',
// no stream wrapper
'(php|file|glob|data|tp|zip|zlib|phar):',
// no data exfiltration
'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>';
}
// no data exfiltration!!!
$content = preg_replace('/HarekazeCTF\{.+\}/i', 'HarekazeCTF{<censored>}', $content);
echo json_encode(['content' => $content]);
获取我们的输入用json方式解码,解码前需要将输入内容进行一个过滤,然后再把file_get_contents的内容在进行一次过滤,两次均通过判断即可输出,输出之前再把flag给你替换掉
题解
思路很简单,file_get_contents支持php://filter,只要用这个伪协议读取文件,将其base64编码即可绕过对内容的过滤和替换,但是问题在于输入也需要一层过滤,且不能出现php字样
这里则是利用json解码时支持Unicode编码的,用Unicode替换掉一两个关键字就可以了
p=\u0070 f=\u0066