漏洞挖掘与防范(进阶篇)

今天学习的漏洞挖掘与防范比较好学,而且对于一些使用的存在漏洞的函数实现也是比较顺利,所以博客的进度也加快了,现在我就把学到的东西和大家分享一下。

1.代码执行漏洞

代码执行漏洞是指应用程序本身过滤不严,用户可以通过请求将代码注入到应用中执行。这样的漏洞如果没有特殊的过滤,相当于直接有一个web后门的存在,该漏洞主要由eval()、assert()、preg_replace()、call_user_func()、call_user_func_array()、array_map()等函数的参数过滤不严格导致,另外还有PHP动态函数($a($b))也是目前出现比较多的。

挖掘经验
eval()和assert()函数导致的代码执行漏洞大多是因为载入缓存或者模块以及对变量的处理不严格导致;preg_replace()函数的代码执行需要存在/e参数,这个函数原本是用来处理字符串的,因此漏洞出现最多的是在对字符串的处理,比如URL、HTML标签以及文章内容等过滤功能;call_user_func()和call_user_func_array()函数的功能是调用函数,多用在框架里面动态调用函数;array_map()函数的作用是调用函数并且处第一个参数外其他参数为数组,通常会写死第一个参数。
除了上面这些函数导致的代码执行漏洞,还有一类非常常见的动态函数的代码执行,写法如下:
$_GET($_POST[“xx”])
基于这种写法变形出来的各种异形,经常被用来当做web后门使用。

代码执行函数
PHP代码执行有多种利用方式,但目前见得最多的是由于函数的使用不当导致的,有eval()、assert()、preg_replace()、call_user_func()、call_user_func_array()、array_map()等函数。

(I)eval和assert函数
这两个函数的作用就是用来动态执行代码,测试代码如下:

在浏览器输入http://localhost/ev.php,测试结果如下:

PS:eval和assert函数执行结果相同。

(II)preg_replace函数
preg_replace函数的作用是对字符串进行正则处理。
看下面一段代码:
mixed preg_replace(mixed $pattern,mixed $replacement,mixed $subject [,int $limit=-1 [, int $count]])
这段代码的含义是搜索$subject中匹配$pattern部分,以$replacement进行替换,而当$pattern处即第一个参数存在e修饰时,$replacement会被当成代码来执行。

我们来看一个最简单的例子:

正则的意思是从$_GET[str]变量里搜索括号[]中间的内容作为第一组结果,preg_replace()函数第二个参数为’\1’代表这里用第一组结果填充。
在浏览器输入http://localhost/pr.php?str=[phpinfo()],结果如下图所示:

(III)调用函数过滤不严
call_user_func()和array_map()等数十个函数有调用其他函数的功能,其中的一个参数作为要调用的函数名,那如果这个传入的函数名可控,那就可以调用以外的函数来执行我们想知道的代码,也就是存在代码执行漏洞。
测试代码如下:

在浏览器输入http://localhost/ca.php?a=assert,当请求ca.php?a=assert,调用了assert函数,并且将phpinfo()作为参数传入,测试结果如下:

动态函数执行
由于PHP的特性原因,PHP的函数可以直接由字符串拼接,这导致了PHP在安全上的控制又加大了难度,比如增加了漏洞数量和提高了PHP后门的查杀难度。
PHP动态函数写法为“变量”,我们来看一个动态函数后门的写法:

代码的意思是接收GET请求的a参数,作为函数,b参数作为函数的参数。
在浏览器输入http://localhost/do.php?a=assert&b=phpinfo(),结果如下:

要挖掘这种形式的代码执行漏洞,需要找可控的动态函数名。

看下面代码:
‘$var[\’\1\’]=”\2”;’
代码意思是吧正则匹配出来的参数1初始化到$var变量中,并且赋值为参数2的值,问题是这段代码在赋值的时候使用的是双引号(”),在php中,如果字符串使用双引号括起来,中间的变量是会正常解析的,测试代码如下:

在浏览器输入,结果如下:

漏洞防范
采用参数白名单过滤,我们可以结合正则表达式来进行白名单限制。

2.命令执行漏洞

代码执行漏洞指得是可以执行PHP脚本代码,而命令执行漏洞指的是可以执行系统或者应用指令(入CMD命令或者bash命令)的漏洞,PHP的命令执行漏洞主要是基于一些函数的参数过滤不严导致,可以执行命令的函数有system()、exec()、shell_exec()、passthru()、pcntl_exec()、popen()、proc_open(),另外反引号(`)也可以执行命令。PHP执行命令使继承Webserver用户的权限,这个用户一般都有权限向web目录写文件。

挖掘经验
命令执行漏洞最多出现在包含环境包的应用里,类似于eyou(亿邮)这类产品,直接在系统安装即可启动自带的Web服务和数据库服务。Web应用服务会有比较多的点之间使用system()、exec()、shell_exec()、passthru()、pcntl_exec()、popen()、proc_open()等函数执行系统命令来调用脚本,用得多了难免会出现漏洞。

命令执行函数
函数system()、exec()、shell_exec()、passthru()以及反引号(`)是可以直接传入命令并且函数会返回执行结果。
测试代码如下:

在浏览器输入http://localhost/sy.php,有结果可以看到执行结果输出了当前WebServer用户

pcntl是PHP的多进程处理扩展,在处理大量任务的情况下会使用得到,使用pcntl需要额外安装,它的函数说明如下:void pcntl_exec(string $path [, array $args[, array $envs ]])
其中$path为可执行程序路径,如果是perl或者Bash脚本,则需要在文件头加上#!/bin/bash来标识可执行程序路径。

popen()、proc_open()函数不会直接返回执行结果,而是返回一个文件指针。下面我们看看popen()函数的用法,它需要两个参数,一个是执行的命令,另外一个是指针文件的连接模式,有r和w表示读和写,测试代码如下:

在浏览器输入

执行完成后,打开D盘目录看到1.txt文件,内容为WebServer用户名,截图如下:

反引号命令执行
反引号也可以执行命令,写法很简单,实际上反引号执行命令是调用的shell_exec()函数。测试代码如下:

在浏览器输入http://localhost/y.php,正常情况输出的结果如下:

当我们在php.ini配置文件中把PHP安全模式打开

在重启WebServer重新加载PHP配置文件,在浏览器输入http://localhost/y.php,结果如下:

这个提示说明反引号执行命令的方式是使用的shell_exec()函数。

漏洞防范
(I)防注入函数
关于命令执行漏洞的防范大概有两种方式:一种是使用PHP再带的命令方注入函数,包括escapeshellcmd()和escapeshellarg(),其中escapeshellcmd()是过滤的整条命令,所以它的参数是一整条命令,escapeshellarg()函数则是用来保证传入命令执行函数里面的参数确实是以字符串参数形式存在的,不能被注入。
测试代码如下:

在浏览器输入,结果如下:

escapeshellarg()函数的功能是过滤参数,将参数限制在一对双引号里,确保参数为一个字符串,因此它会把双引号替换为空格,测试代码如下:

在浏览器输入,结果如下:

(II参数白名单)
参数白名单方式在大多数由于参数过滤不严产生的漏洞中都很好用,是一种通用修复方法。

猜你喜欢

转载自blog.csdn.net/qq_36197704/article/details/81623808