SQL 注入漏洞
SQL 注入是十分常见的漏洞了,之所以存在 SQL 注入,是因为程序对输入的参数过滤的不够严格,或者在对字符串的处理存在偏差导致防御失效。
数字型 SQL 注入
其实大多数的 CMS 都会做一些 SQL 注入的防御,例如设置 magic_quotes_gpc=on 或者使用 addslashes() 函数一个很简单的方式就把单引号给限制了,因此类似如下的 SQL 语句是很难产生注入。
$sql = "select * from tp_user where username='".$_POST["username"]."'"
数字型 SQL 注入的问题就在于,如果语句并未使用单引号来包裹变量,例如如下语句。那么即便转义了单引号,也达不到防御的效果,因为根本就不需要使用单引号来闭合语句。
$sql = "select * from tp_user where username=".$_POST["username"]
在挖掘这类漏洞,当然就是观察 SQL 语句的拼接情况,是否对用户的输入进行处理。由于是数字型,只要关心输入的数据是否被强制转换成数字了,如果没有,那么很可能存在注入。
案例
S-CMS V3.0前台SQL注入
漏洞代码如下:
可以看到在第 83 行处接收到了传递来的参数 $_POST['pageid']
,而变量 $pageid
为经过处理就被拼接进了 92 行的 SQL 语句之中。观察 92 行的 SQL 语句可以看到,并未使用单引号进行保护,因此此处是一处数字型 SQL 注入。
UsualToolCMS v8.0 后台 SQL 注入
问题代码如下:
同样的可以看到传递的 $_GET['id']
未进行处理就拼接进了 SQL 语句。
防御方法
不难看出,如果将传入的参数强制转换成数字那么就能补上这类漏洞。
字符型 SQL 注入
前面提到了,由于变量收到单引号包裹保护,恶意输入的单引号又被转义了,因此很难进行 SQL 注入。但是又由于对字符串的处理不当或者在某种特定情况下,导致防御失效的案例还是有的。举个小例子,如下 SQL 语句:
$sql = "select * from tp_user where username='".$_POST['username']."' and password = '".$_POST['password']."'"
这种情况下如果对反斜线未做转义处理,就会导致注入的产生。当 $_POST['username']
的值为\
, $_POST['password']
的值为 or 1=1 #
。语句的拼接结果如下:
select * from tp_user where username='\' and password = ' or 1=1 #'
放入数据库中执行看看。
可以看到语句正常执行了,并且查出了所有数据的信息。篇幅原因,此处不对原理进行详细解释。原理参考:
因此,在审计的过程中,看到双变量的 SQL 语句,不妨看看反斜线是否被处理了,没准就是一个突破口。
再来看看对字符串处理不当造成的注入。直接看案例吧。
案例
Maccms8.0 SQL 注入 :
MKCMS 前台 SQL 注入:
可以看到在第三行出,使用了 stripslashes()
函数使得原本已经转义的单引号又恢复成未转义的状态,导致漏洞的发生。其实此处不太理解,为什么这里要去除转义。
总之面对字符型注入,要关注一下是否可绕过。可能开发者在处理字符串的时候,出现了例如上面链接里提到的长度限制的问题,或者反斜线未做处理的问题导致注入产生。
防御方法
对变量使用单引号进行包裹,并且对用户输入的例如引号之类的特殊字符进行处理。在进行字符串处理的时候,要注意避免使得原先的防御被绕过。
CSRF 漏洞
相比 SQL 注入来说 CSRF 漏洞是最好挖掘的,仅需观察表单中是否存在一个 token 或者验证码来验证请求是正常用户发出的,或者观察程序中是否有对 reference 进行判断处理,也就是判断请求的来源。如果都没有,恭喜你,这里很可能是一出 CSRF 漏洞。
CSRF 的漏洞虽然容易挖掘,但是危害也相对 SQL 注入来说没那么直接。类似于反射型 XSS,CSRF 需要正常用户的交互,即攻击者需要诱使普通用户完成一些操作才可以触发漏洞。
挖掘思路,如上文所说的,观察某个功能在执行的时候是否有验证请求来源。
案例
zzzCMS V1.7.1 版本 CSRF 漏洞
在 zzzCMS 中,存在多处 CSRF 漏洞,此处仅对添加管理员这一处进行举例。
如上代码,可以看出在接受各种参数后,对数据进行格式判断,而未对请求的发起和来源是否来自正常用户进行验证,导致攻击者只需要构造相应的表单,诱使管理员访问或点击。在不知情的情况下,攻击者就完成了创建一个管理员帐号。表单内容如下:
<html>
<form action='http://127.0.0.1/zzz17/admin261/save.php?act=user' method="post">
<input type='hidden' name='u_gid' value='2'/>
<input type='hidden' name='username' value='zhhhy'/>
<input type='hidden' name='password' value='6192288a'/>
<input type='hidden' name='truename' value='zhhhy'/>
<input type='hidden' name='mobile' value='15260131659'/>
<input type='hidden' name='face' value='/zzz/plugins/face/face01.png'/>
<input type='submit' value='点击有惊喜'/>
</form>
</html>
防御方法
增加验证码,不过可能会影响用户体验。比较好的是加一个 token 值以及验证请求来源。
文件操作相关的漏洞
文件相关的操作其实很多,我把他统成一大类。例如,任意文件重命名、任意文件下载、任意文件复制等。在我发现的几个案例里,对文件后缀名限制的比较严格,以至于无法 getshell。但是,不能 getshell,这些漏洞就没有利用价值了吗?当然不是。
挖掘漏洞的时候,重点观察一下被操作的文件的后缀是否被限制的严格,例如是否可以修改 PHP 文件。再看看跳转符号是否被过滤或者路径有没有被限制,可不可以穿梭任意目录。
来看 doorgetsCMS 的几个案例:
案例
doorGets 复制任意文件
在第 39 行处执行了将一个文件进行复制。在 34 和 35 行对路径进行判断,但是并未过滤../
跳转符号。那么我们就可以利用跳转符号进行路径穿越,跳到一些配置文件的目录里,然后将配置文件复制出来。例如 Apache 的配置文件,将这个文件复制到网站的根目录下,由于是静态文本文件,直接访问就可以获取到里面的内容造成信息泄露的效果。
doorGets 任意文件下载
在代码的第 36 行处进行文件下载。对传入的 $path
未作处理,可以进行任意目录跳转,于是可以把任意文件下载下来。
如下 payload 就可以把 php 文件下载下来。
http://domain.com/fileman/php/downloaddir.php?d=/fileman/Uploads/../../config
doorGets 任意文件重命名
同样的,在 36 行处执行重命名操作,也没有进行对跳转符号进行限制。一个思路就是把 PHP 重命名成 HTML 文件,这样就可以把 PHP 文件的内容给泄露出来。
payload 如下:
f=%2Ffileman%2FUploads%2F..%2F..%2Fconfig%2Fconfig.php&n=..%2Ffileman%2FUploads%2Ftest.html
防御方法
限制文件的路径避免路径穿越的发生,严格控制文件后缀名