整合绕过。
接下来将展示几个对关键词进行过滤的简单(绕过)方法。
(1)过滤代码
('/(and|or|union|where|limit)/I',$id)
绕过方法:对关键词and,or,union,where,limit进行了过滤,构造代码类似于11||( user from users group by =1 )= 'admin'即可绕过。
(2)过滤代码
('/|order|||eval||||j
|link|'|%|/*|*|../|./|,|.|--|"|and,$str)
绕过方法:仅对小写的注入关键词进行了过滤,大写即可绕过。
三、XSS审计
XSS攻击是近些年盛行的一种攻击方式,恶意攻击者往Web页面里插入恶意html代码,当用户浏览该网页时,嵌入其中的html代码会被执行,从而达到恶意攻击用户的特殊目的。而PHP中对XSS的审计又是怎样的呢?
这是一个的历史漏洞了,第一时间在X3.1版本的一个补丁中修复了这一漏洞,不过对于仍然使用着 X3.1旧版本(其实绝大多数都在使用旧版本,因为补丁发布的时候X3.1已经发布很久了)及以下版本的网站来说,这个漏洞依然有效。下面我们来体验一下这个漏洞的审计过程。
有关这个漏洞的代码在\\下的.php中。
119 if($) {
120 if(($, 'ed2k://') != FALSE) {
121 $ = ("/ed2k://(.+?)//e", "('\1')",
$);
122 }
123 }
很显然,这段代码用于检测是否启用ed2k协议并在第121行对ed2k链接进行了处理。为了让大家更清晰地理解这些PHP代码,这里假设您对PHP的掌握处于入门阶段,对涉及的一些API做一个简单介绍。121行中的函数原型如下。
mixed ( mixed $ , mixed $ , mixed
$ [, int $limit = -1 [, int &$count ]] )
// 执行一个正则表达式的搜索和替换:搜索中匹配的部分,用进行替换
对于刚刚接触代码审计的初学者来说,可能会感觉自己对代码的掌握程度不够,没关系,每种语言的官方手册对每个函数都有详细解释以供开发者学习。对于有一定经验的审计者来说,开源项目的手册或说明文中仍有很多重要的部分,而且同一厂商过去的漏洞也可能为审计引导一个方向,不要羞于站在巨人的肩膀上!
这个函数调用()函数对$进行正则处理,下面来跟踪处理函数()。
320 ($url) {
321 $_G;
322 list(,$type, $name, $size,) = ('|', $url);
//用来读取连接中的类型,名称与大小
323 $url = 'ed2k://'.$url.'/';
324 $name = ($name);
325 if($type == 'file') {
326 $ = 'ed2k_'.(3);
327 '
blank">'.(($name)).'
('.($size).')';
328 } else {
329 ''.$url.'';
330 }
331 }
从这段代码中可以看出,()并没有对参数$size进行安全处理,甚至没有对$size进行类型转换(暂且认为这是程序员的疏忽),因此函数($size)中传入的是字符串类型的$size变量。
下一步跟进()函数,它在同目录下的.php中:
1601 ($size) {
1602 if($size >= ) {
1603 $size = round($size/ * 100)/100 . 'GB';
1604 } else if($size >= ) {
1605 $size = round($size / * 100) / 100 .' MB';
1606 } else if($size >= 1024) {
1607 $size = round($size / 1024 * 100) / 100 . 'KB';
1608 } else {
1609 $size = $size . 'Bytes';
1610 }
1611 $size;
1612 }
这段代码用来对文件大小进行划分,字符串类型的$size的值在与类型比较时,会被强制转换成类型后再进行比较。如果传入的$size并不是纯数字字符串,那么$size的值会被转换成NaN(Not a ),不会触发前三个if语句,直接进入else语句,而else中的函数并没有对$size进行类型转换,直接与'Bytes'进行了配对,配对后的字符串被最终返回给.php中121行的$,然后被输出。
第1609行代码在×3.1补丁中被替换为:
1609 $size = ($size) . ' Bytes';
函数将$size转换为整型,因此避免了对于$size的XSS攻击。
下面来实际测试一下:
在 X3.1或以下版本的论坛中发帖时插入这样一句:
ed2k://|file|xss|'+alert(123)+'|xss/
图16所示的对话框证明了漏洞的存在。
图16 XSS对话框
顺便提一下,这个漏洞因为格式限制不能包含各种引号。不要灰心,这里可以用.write(.(... ...));的方式写入html标签,如,这里的属性src不需要引号即可加载外部JS文件,进而利用这个漏洞。
通过简单地分析可以发现,程序员为了简化代码(其实打完补丁之后并没有简化)让字符串类型的$size通过强制类型转换与整型比较,然后直接将$size与表示文件大小、单位的字符串进行连接,这种简化是一个很不好的习惯,在编写代码时应避免利用强制类型转换来比较不同类型变量,这种方法往往会被攻击者利用(就像这里一样)。
四、变量覆盖
关于变量覆盖,首先要了解PHP的特性。PHP是一种类型松散的语言,它根据变量的值自动地把变量转换为正确的数据类型。变量覆盖就是指攻击者在攻击时给予其特定的值,并覆盖原有的固定值,从而引发一些安全问题。下面介绍常见的变量覆盖。
1、变量初始化
此类变量覆盖需要在=on时才能发生,下面来看“乌云某白帽子”的一个漏洞。
这里变量where并没有进行初始化,而是直接代入了查询语句,从而导致变量覆盖,在这里引发了注入,注入格式为?=list&where=注入语句。
2、危险函数引发的变量覆盖
()函数的作用是从数组中把变量导入到当前的符号表中。当函数中type参数为默认值、传递的变量同名时,会进行覆盖,从而引发其他安全问题。下面来看某开源程序代码。
第4行的($)命令导致了变量覆盖,因此我们可以直接覆盖掉$table,并补全语句,从而进行注入。
五、命令执行
命令执行是PHP中常见的一种漏洞,这种漏洞的危害较大,直接威胁到服务器的安全。在PHP中,命令执行往往发生在eval()、()、()、exec()、()、()、()这些高危函数上。因为开发者的疏忽,这些函数所执行的命令有时会出现用户可控的情况,从而导致攻击者提交恶意代码达到攻击目的。下面将对其进行分析。
1、常见的命令执行函数
(1)eval()
该函数是把字符串按照PHP代码来执行。语法格式:
eval();
下面是一段问题代码:
这是一段很简单的代码,可以看到代码中将参数com的值传递给变量com,然后直接将变量com的值当作PHP代码来执行,于是漏洞便产生了。当令参数com为();时,结果如图17所示。
图17 执行命令
(2)()
该函数类似C语言的()函数,用来执行指令discuz代码,并输出结果,语法格式:
( , int []);
下面是一段问题代码:
当参数com为时,结果如图18所示。
图18 执行命令
当参数com为ping 时,结果如图19所示。
图19 执行ping命令
(3)()
该函数返回用户自定义函数作用后的数组。回调函数接收的参数数目应该和传递给()函数的数组数目一致,语法格式:
(, , , ...)
下面是一段问题代码:
令上述代码中的参数为,结果如图20所示。
图20 执行命令
2、动态函数
在实际开发中,有的程序员想动态调用某些函数,却往往会忽略动态函数的风险。
下面是一段问题代码:
在上述代码中,程序员原意是想动态调用A函数和B函数,所以把变量作为函数名,并且可控。但这其实等同于可以执行任意函数,当直接令参数为,参数com为ping 时,结果如图21所示。
图21 直接执行ping命令
六、上传绕过
熟悉渗透的朋友一定知道文件上传是的主要途径之一,是用来获取Web权限的重要漏洞方式,也常常是Web渗透的最后一关,可见其重要性。下面便来剖析常见的文件上传绕过漏洞。
1、绕过
先来看一段实例代码:
下面来查看函数。
可以看到调用的是一段代码,我们再回到函数中。
这段代码判断当文件类型不合法时便调用,但无论调用是否失败,都会执行上传代码,因此只要禁用就能知道上传文件的路径了。
这里直接改包代替(因为是客户端脚本语言,只对浏览器进行了限制),如图22所示。
图22 改包代替
2、文件头验证绕过
问题代码如下。
上面的代码对文件类型进行了判断,只允许了image/gif这种类型。但是人们仍可以伪造这样的文件头进行上传。
3、逻辑问题
实例代码如下。
问题出在后缀判断和函数上,先来看一下后缀判断。
if($[0] == ($[1]) && $[1] ==
"allow")
当上传××.jpg.php时:
$[0]=××
$[1]=jpg
$[2]=php
但可以看到if语句并没有判断$[2],因此成功绕过,进入函数。
($[''] . “/” . $[$]['name'], $user_
dat[''] . "/" . $[0] . "." . ($[1]));
这里会将之前上传的××.jpg.php改名为××.jpg。但根据函数特性,当二次上传同名文件时,例如××.jpg.php,紧接着会进入流程,尝试被改名为××.jpg,但因为××.jpg已经存在了,所以成功上传了××.jpg.php。
七、文件包含
文件包含也是PHP中常见的一种漏洞,其结果往往就是,其危害极大。那什么是文件包含呢?它往往出现在()、 ()、()、()、fopen、这些加载文件的函数上。因为对文件名没有过滤,导致攻击者可以包含任意文件或特定文件,从而达到攻击目的。
1、漏洞成因
问题代码如下。
这段代码的初衷应该是想调用某文件的样式和功能。但因为这里dir为用户可控,所以可以调用任意文件。而问题就在于此,如果攻击者上传一个尾部有PHP恶意代码的图片,如/××.jpg,再访问?dir=/××.jpg,那么恶意代码就会被引入当前文件并执行,从而达到攻击目的。
当然,文件包含并不仅限于包含上传的文件,也可以包含一些配置文件。
?dir=.
?dir=../../../../../../web.
?dir=../../../../../../../../../var/log//error.log
?dir=../../../../../../../../../proc/.gz(需root权限)
?dir=../../../../../../../../../etc/(需root权限)
2、绕过限制
在实际开发中,开发者为了避免受其害,对包含的路径做了很多限制,如下面这段代码。
从这里可以看到,开发者对目录和后缀名都进行了控制。但人们可以提交../轻松绕过对目录的限制,同时用截断绕过对后缀的限制。如?dir=../../../../../../../etc/,从而包含恶意文件。
截断需要=off,PHP版本小于5.3.4时才能实现。
当然,对于上述代码,还有其他方法绕过其限制,如路径长度截断(PHP版本小于5.2.8,Linux下文件名长度大于4096字节,下长度大于256字节)、点号截断(PHP版本小于5.2.8,只适用于系统discuz代码,点号长度须大于256字节)等。
再来看一段对目录进行过滤的代码。
Print.php:
这段过滤代码是用函数将../替换成./,从而使攻击者无法用../跳出目录。不过当提交.../时,因为会将../替换成./,所以又再次变成了../,从而跳出了目录。因此当人们提交?dir=.../print.php时,就成功包含了文件。
测试结果如图23所示。
图23 包含本地文件
3、任意文件读取
是最常见的文件读取函数,用来把整个文件读入一个字符串中。语法格式:
(path, , , start, )
也就是我们常说的任意文件读取,控制要读取文件的路径,从而达到攻击目的,例如读取一些数据库配置文件等。
先来看一段代码:
提交?dir=/data/web.,结果如图24所示。
图24 读取本地文件
八、写在最后
随着网络的普及,商业网站、政府网站、个人博客不计其数。而搭建网站的门槛也变得越来越低,搭建过程开始变得模式化、智能化,很多并不懂网站开发的人也可以使用开源软件搭建属于自己的网站,并且因为开源软件价格低廉,很多企业、政府也会选择安全性高、口碑好的开源软件进行网站搭建。因此,开源软件的安全性显得尤为重要。如今随着PHP被广泛使用,PHP在开源市场的地位越来越高,这里以小结的形式来讲讲开源审计的经验。
在审计一开始,首先应该通读全局文件,看看有没有做一些全局过滤,并且大致了解程序的结构。如果做了全局过滤,那可以尝试对过滤代码进行,一旦成功便是全盘沦陷。
在审计中,应特别留意用户可控的参数。而对于可控参数的查找,可以检索一些传参数组,使审计更加高效,常见的传参数组如表1。
表1 常见传参数组
当找到可控参数时,就可以分析其进行了几次传递,有没有进入查询语句,经历了几个函数。而说到函数,在PHP审计中,高危函数的查找也是极其高效的方法之一,常见的高危函数如表2所示。
表2 常见高危函数
在开源程序中,出现更多的是二次漏洞。可以想象一下,假如现在有很多物品需要带走,但一次带不了那么多,那可以分两次拿。二次漏洞也是如此,把一次攻击分两次进行,但能达到一样的目的,并且这种漏洞的隐蔽性较高,在大中型开源软件中也常常出现,同时这一类漏洞相对一次漏洞而言更耗脑力,更考验审计者的耐心和体力。
当然代码审计中出现的漏洞远不止本文所说的这些,还有如拒绝服务、CSRF、平行权限、验证绕过等。
版权说明:如涉版权问题,请与我们联系,谢谢!
限时特惠:本站持续每日更新海量各大内部创业课程,一年会员仅需要98元,全站资源免费下载
点击查看详情
站长微信:Jiucxh