Gentle_knife's Studio.

奇妙的json_decode

Word count: 641Reading time: 2 min
2025/08/17
loading

让数据变成合法的 JSON

感谢 Rina 带来的奇妙知识点!
题目情境:

1
2
3
4
5
<?php
highlight_file(__FILE__);

// HINT: flag is in /flag, and no need to RCE
echo json_decode(file_get_contents($_POST["file"]));

json_decode 会把JSON 格式的字符串,转成 PHP 可用的数据类型。如果 JSON 不合法,json_decode 会返回 null。也就是说我们要用 json 的格式读取字符串类型的 flag。

https://github.com/ambionics/wrapwrap

wrapwrap 是一个自动生成复杂 php://filter 链的工具。当我们只能控制 file_get_contents($_POST['url']) 里面的参数,需要让文件内容符合某种格式(比如 JSON/XML),才能被程序显示出来,我们需要让在文件内容前后 加上特定的前缀和后缀,让数据变成合法的 JSON 或 XML。wrapwrap 这个脚本可以自动帮我们完成这件事。

示例命令:

./wrapwrap.py /etc/passwd '{"message":"' '"}' 1000

第一个单引号里面是前缀,第二个单引号里面是后缀,1000 是要读的参数长度。

但是我们这里直接把/etc/passwd 改成/flag 也是读不出来的,不是脚本的问题, 而是 json_decode 本身的特性:

1
2
3
echo json_decode("{'message':'123'}");
echo json_decode('123');
echo json_decode(123);

可以发现只会打印后面两个 123。

json_decode 只会打印字符串,而不会打印完整的 json 对象。

所以这里把./wrapwrap.py /flag '"' '"' 50生成的 chain.txt 放到参数里面就行。

用 JSON 的 Unicode 字符绕过正则

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<?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]);

\uXXXX可以在JSON中转义字符,\u后面代表的是十六进制的unicode编码。

这里过滤了 flag,我们要读 flag。正则表达式只认php这三个字符,JSON 认 unicode 编码,所以我们可以用 unicode 来绕过。

[HarekazeCTF2019]encode_and_encode JSON小技巧_ctf json-CSDN博客

json_decode函数详解_w3cschool

php裸文件包含 | Dar1in9’s Blog

CATALOG
  1. 1. 让数据变成合法的 JSON
  2. 2. 用 JSON 的 Unicode 字符绕过正则