3.3 根据功能点定向审计
在有了一定的代码审计经验之后,一定会知道哪些功能点通常会有哪些漏洞,在我们想要快速挖掘漏洞的时候就可以这样来做,首先安装好并且运行程序,到处点点,浏览一下,看下程序有哪些功能,这些功能的程序文件分别是怎么样的,是独立的模块还是以插件形式存在,或者是写在一个通用类里面,然后多处调用。在了解这些功能的存在形式后,可以先寻找经常会出问题的功能点,简单黑盒测试一下,如果没有发现很普通、很常见的漏洞,再去读这个功能的代码,这样我们读起来就可以略过一些刚才黑盒测试过的点,提高审计速度。
根据经验,我们来简单介绍几个功能点经常会出现的漏洞,如下所示:
1)文件上传功能 。这里说的文件上传在很多功能点都会出现,比如像文章编辑、资料编辑、头像上传、附件上传,这个功能最常见的漏洞就是任意文件上传了,后端程序没有严格地限制上传文件的格式,导致可以直接上传或者存在绕过的情况,而除了文件上传功能外,还经常发生SQL注入漏洞。因为一般程序员都不会注意到对文件名进行过滤,但是又需要把文件名保存到数据库中,所以就会存在SQL注入漏洞。
2)文件管理功能 。在文件管理功能中,如果程序将文件名或者文件路径直接在参数中传递,则很有可能会存在任意文件操作的漏洞,比如任意文件读取等,利用的方式是在路径中使用../或者..\跳转目录,如图3-12所示。
除了任意文件操作漏洞以外,还可能会存在XSS漏洞,程序会在页面中输出文件名,而通常会疏忽对文件名进行过滤,导致可以在数据库中存入带有尖括号等特殊符号的文件名,最后显示在页面上的时候就会被执行。
3)登录认证功能 。登录认证功能不是指一个登录过程,而是整个操作过程中的认证,目前的认证方式大多是基于Cookie和Session,不少程序会把当前登录的用户账号等认证信息放到Cookie中,或许是加密方式,是为了保持用户可以长时间登录,不会一退出浏览器或者Session超时就退出账户,进行操作的时候直接从Cookie中读取出当前用户信息,这里就存在一个算法可信的问题,如果这段Cookie信息没有加salt一类的东西,就可以导致任意用户登录漏洞,只要知道用户的部分信息,即可生成认证令牌,甚至有的程序会直接把用户名明文放到Cookie中,操作的时候直接取这个用户名的数据,这也是常说的越权漏洞。
图 3-12
ESPCMS就多次被曝光存在这个漏洞,具体的漏洞分析在乌云上面可以直接看到,其中一个漏洞信息如下,感兴趣的读者可以研究一下:
缺陷编号:WooYun-2015-90324
漏洞标题:ESPCMS所有版本任意用户登录
相关厂商:易思ESPCMS企业网站管理系统
漏洞作者:路人甲
4)找回密码功能 。找回密码虽然看起来不像任意文件上传这种可以危害到服务器安全的漏洞,但是如果可以重置管理员的密码,也是可以间接控制业务权限甚至拿到服务器权限的。而找回密码功能的漏洞有很多利用场景,最常见的是验证码爆破,目前特别是APP应用,请求后端验证码的时候大多是4位,并且没有限制验证码错误次数和有效时间,于是就出现了爆破的漏洞。除此之外,还有验证凭证的算法,这需要在代码中才能看到,所以我们做代码审计的时候可以看看这个算法是否可信。
这些功能点上的漏洞需要我们多读代码才能积累经验。
BugFree重装漏洞案例
针对功能点的审计是相对简单的,不过在使用这种方式审计之前建议先了解整个程序的架构设计和运行流程,程序重装漏洞在早期是比较常见的,我们来看看BugFree的程序安装功能,该程序之前被papaver爆出存在多个漏洞,其中就有一个重装漏洞。
BugFree安装文件在install\index.php,代码如下:
< ? php
require_once ( 'func.inc.php' );
set_time_limit ( 0 );
error_reporting ( E_ERROR );
// 基本路径
define ( 'BASEPATH' , realpath ( dirname ( dirname ( __FILE__ ))));
// upload path
define ( 'UPLOADPATH' , realpath ( dirname ( dirname ( dirname ( __FILE__ )))) .DIRECTORY_SEPARATOR.'BugFile' );
// 配置样本文件路径
define ( 'CONFIG_SAMPLE_FILE' , BASEPATH . '/protected/config/main.sample.php' );
// 配置文件路径
define ( 'CONFIG_FILE' , BASEPATH . '/protected/config/main.php' );
看这段代码首先包含了'func.inc.php'文件,跟进这个文件可以看到一些读取配置文件、检查目录权限以及服务器变量等功能的函数,下方则是定义配置文件的路径,继续往下走,真正进行程序逻辑流程的地方如下代码所示:
$action = isset ( $_REQUEST['action'] ) ? $_REQUEST['action'] : CHECK ;
if ( is_file ( "install.lock" ) && $action ! = UPGRADED && $action ! = INSTALLED )
{
header ( "location : ../index.php" );
}
这段代码存在一个逻辑漏洞,首先判断install.lock文件是否存在以及action参数值是否升级完成和安装完成,如果是,则跳转到程序首页,这里仅仅使用了
header ( "location : ../index.php" );
并没有使用die()或者exit()等函数退出程序流程,这个跳转只是HTTP头的跳转,下方代码依然会继续执行,这时候如果使用浏览器请求install/index.php文件则会跳转到首页,我们用burp试试,效果如图3-13所示。
图 3-13
可以看到程序又可以再次安装。