PHP-Audit-Labs
靶场地址:https://www.ripstech.com/php-security-calendar-2017/
在代码$file = preg_replace("/[^a-z.-_]/", "", $token);
处存在绕过,preg_replace匹配除了 a 字符到 z 字符、. 字符到 _ 字符之间的所有字符,在调用performAction
方法的时候,if delete
则可触发攻击链,攻击者可以构造../../../../config.php
进行任意文件删除。
CTF
index.php
1 |
|
flag.php
1 | <?php $flag = "HRCTF{Pr3g_R3plac3_1s_Int3r3sting}";?> |
其中正则表达式的部分可以参考学习:PHP正则表达式的字符类
alnum | 字母和数字 |
---|---|
alpha | 字母 |
ascii | 0 - 127的ascii字符 |
blank | 空格和水平制表符 |
cntrl | 控制字符 |
digit | 十进制数(same as \d) |
graph | 打印字符, 不包括空格 |
lower | 小写字母 |
打印字符,包含空格 | |
punct | 打印字符, 不包括字母和数字 |
space | 空白字符 (比\s多垂直制表符) |
upper | 大写字母 |
word | 单词字符(same as \w) |
xdigit | 十六进制数字 |
题目中总共有三处正则匹配,我们分别来看一下其对应的含义。第一处的正则 /^[[:graph:]]{12,}$/ 为:匹配到可打印字符12个以上(包含12),^ 号表示必须以某类字符开头,$ 号表示必须以某类字符结尾。第二处正则表达式:
1 | $reg = '/([[:punct:]]+|[[:digit:]]+|[[:upper:]]+|[[:lower:]]+)/'; |
表示字符串中,把连续的符号、数字、大写、小写,作为一段,至少分六段,例如我们输入 H0ng+Ri 则匹配到的子串为 H 0 ng + R i 。第三处的正则表达式:
1 | $ps = array('punct', 'digit', 'upper', 'lower'); |
表示为输入的字符串至少含有符号、数字、大写、小写中的三种类型。然后题目最后将 $password 与42进行了弱比较。所以我们的payload为:
1 | password=42.00e+00000 |
通过正则写配置文件
题目链接:https://github.com/wonderkun/CTF_web/tree/dcf36cb9ba9a580a4e8d92b43480b6575fed2c3a/web200-7
ctf.php
1 |
|
config.php 的内容如下:
1 |
|
要求是要getshell,这个场景十分经典,常用在修改配置文件写入的时候。 此处不存在之前说的那个配置文件中用的是"双引号"引起任意代码执行的问题,这这里面用的是单引号,而且 addslashes()处理过了,看似很安全,但是对于脑子里有个黑洞的搞安全的人来讲,这个还真是有问题的.
方法一,利用换行符来绕过正则匹配的问题
可以看到正则匹配的是以下内容:
1 | $option='任意内容' |
任意内容里面是可以包含转移符 \ 的,所以我们利用下面的方法:
1 | http://127.0.0.1/index.php?option=a';%0aphpinfo();// |
执行完第一个之后,config.php中的内容为:
1 | <?php |
但是这样并没有办法执行phpinfo(),因为我们插入的 单引号 被转移掉了,所以phpinfo()还是在单引号的包裹之内. 我们在访问下面这个
1 | http://127.0.0.1/index.php?option=a |
因为正则 .*
会匹配行内的任意字符无数次.所以 \ 也被认为是其中的一部分,也会被替换掉,执行完之后,config.php中的内容为:
1 | <?php |
转义符就被替换掉了,就成功的getshell.
利用 preg_replace() 函数的第二个参数的问题
先看官方对preg_replace()函数的描述manual 函数原型:
1 | mixed preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit = -1 [, int &$count ]] ) |
对replacement的描述.
replacement中可以包含后向引用\n 或(php 4.0.4以上可用)$n,语法上首选后者。 每个 这样的引用将被匹配到的第n个捕获子组捕获到的文本替换。 n 可以是0-99,\0和$0代表完整的模式匹配文本。
所以我们可以用:
1 | http://127.0.0.1/test/ph.php?option=;phpinfo(); |
执行第一条后config.php的内容为:
1 | <?php |
再执行第二条后config.php的内容为:
1 | <?php |
刚好闭合掉了前后的两个单引号中间的逃脱出来了.想出这个办法的人,思路真是可以的.
转载:
https://github.com/wonderkun/CTF_web/tree/dcf36cb9ba9a580a4e8d92b43480b6575fed2c3a/web200-7