php代码审计 参数,PHP代码审计05之正则使

本文详细分析了PHP代码审计中正则使用不严谨导致的任意文件删除漏洞,通过讲解PHP的preg_replace()函数及CTF题目加深理解。在CTF练习中,涉及了对PHP正则字符类的熟悉,解析了代码中的正则表达式含义,并构造了payload。最后,通过实例分析了一个基于ThinkPHP框架的CMS系统中类似漏洞,讨论了如何利用str_replace()函数进行路径穿越攻击。
摘要由CSDN通过智能技术生成

根据红日安全写的文章,学习PHP代码审计的第五节内容,题目均来自PHP SECURITY CALENDAR 2017,讲完题目会用一道CTF的题目和实例来加深巩固。这是之前写的,有兴趣可以去看看:

PHP代码审计01之in_array()函数缺陷

PHP代码审计02之filter_var()函数缺陷

PHP代码审计03之实例化任意对象漏洞

PHP代码审计04之strpos函数使用不当

2|0漏洞分析

下面看题目,代码如下:

1460000038726492

题目漏洞是正则使用不严谨导致任意文件删除的漏洞,现在来具体分析,引起漏洞的地方在上面代码的21行,这里用到了preg_replace()函数,我们打开PHP手册来看看对这个函数的定义如下:

1460000038726491

了解了函数的用法,看上面代码,action=delete&data=../../config.php

将删除config.php文件。

3|0CTF练习

通过上面的讲解,来用一道CTF题目来练习一下,也是关于正则的问题,先看代码:

//index.php

include 'flag.php';

if ("POST" == $_SERVER['REQUEST_METHOD'])

{

$password = $_POST['password'];

if (0 >= preg_match('/^[[:graph:]]{12,}$/', $password))

{

echo 'Wrong Format';

exit;

}

while (TRUE)

{

$reg = '/([[:punct:]]+|[[:digit:]]+|[[:upper:]]+|[[:lower:]]+)/';

if (6 > preg_match_all($reg, $password, $arr))

break;

$c = 0;

$ps = array('punct', 'digit', 'upper', 'lower');

foreach ($ps as $pt)

{

if (preg_match("/[[:$pt:]]+/", $password))

$c += 1;

}

if ($c < 3) break;

if ("42" == $password) echo $flag;

else echo 'Wrong password';

exit;

}

}

highlight_file(__FILE__);

?>

//flag.php

这道题目考察了是否熟悉PHP正则表达的字符类,大体是下面这个表格:

alnum

字母和数字

alpha

字母

ascii

0 - 127的ascii字符

blank

空格和水平制表符

cntrl

控制字符

digit

十进制数(same as d)

graph

打印字符, 不包括空格

lower

小写字母

print

打印字符,包含空格

punct

打印字符, 不包括字母和数字

space

空白字符 (比s多垂直制表符)

upper

大写字母

word

单词字符(same as w)

xdigit

十六进制数字

想要更加详细的了解,建议翻阅PHP手册,了解了字符类,下面来分析代码,上面一共三处正则表达,第一处如下:

if (0 >= preg_match('/^[[:graph:]]{12,}$/', $password))

它表示的含义是匹配到可打印字符12往上包含12,^表示必须某类字符开头,$表示必须某类字符结尾。

第二处正则如下:

$reg = '/([[:punct:]]+|[[:digit:]]+|[[:upper:]]+|[[:lower:]]+)/';

if (6 > preg_match_all($reg, $password, $arr))

break;

它表示的含义是,把连续的字符,数字,大写,小写作为一段,最少分成六段,比如Test+0He 会分为T est + 0 H e六段。

下面看第三处正则:

$ps = array('punct', 'digit', 'upper', 'lower');

foreach ($ps as $pt)

{

if (preg_match("/[[:$pt:]]+/", $password))

$c += 1;

}

if ($c < 3) break;

if ("42" == $password) echo $flag;

这里的含义是输入的字符必须包含字符,数字,大写,小写其中的三种往上。最后与42进行弱类型比较,都符合就输出flag,现在都解读清楚了,让咱们构造payload结果如下:

1460000038726486

4|0实例分析

通过例题和CTF题目的讲解,是不是感觉棒棒的,现在咱们来分析实例吧,实例是LvyeCMS3.1,是基于ThinkPHP3.2.3框架。这个实例存在的漏洞也是函数使用不规范被绕过,导致任意文件删除。下面来具体分析:

先查看入口文件index.php

1460000038726493

可以看到公共目录,应用目录等一些信息。接下来再看看目录结构:

1460000038726487

而漏洞在Application/Template/Controller/StyleController.class.php文件中,具体如下:

1460000038726490

看代码第117行,这里是获取目录路径,参数也是我们可以控制的,再向后看,用到了str_replace()函数,它是个字符串替换函数,具体说明如下:

1460000038726488

再这里起到的作用就是将'..', '../', './', '.'替换为空。但是这里是可以绕过的,如果我们输入.....///呢,会发生什么?是不是正好构造成了../,举个小例子会更清楚,如下:

1460000038726484

构造出../我们就可以穿越目录了,现在访问install.php文件会提示已安装,如下图:

1460000038726485

然后尝试删除lvyecms/Application/Install/目录下的 install.lock 文件,构造payload如下:

http://www.xxx.com/index.php?g=Template&m=Style&a=delete&dir=.....///Application/Install/&file=install.lock

1460000038726489a-z.-_ ↩

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值