防注入程序带来的攻击及防范

本文已经在《黑客手册》发表 经同意放出 转载请说明

ps: sql通用防注入3.1β版已更正此问题

谨以此文献给我心爱的小猪–璇。
现在基于web的攻击一般都是注入。导致注入的原因一般为对变量的过滤不完全,从而可以使入侵者非法执行程序或查询修改任意数据。随着注入攻击的愈演愈烈,一些专门的过滤代码应运而生。但一些过滤代码的不完善很可能导致新的攻击。下面就以目前应用最广泛的过滤代码–SQL通用防注入程序为下列说明漏洞的成因、利用方法及防范措施。
SQL通用防注入程序是由火狐的枫知秋编写的,功能相当完善的防注入代码。它能对定义的过滤字符实现get提交的过滤,并能记录攻击者的IP提交的数据信息。使用时只须在要防注入的文件头中加入代码<!–#Include File=”WrSky_Sql.Asp”–>就可以实现对变量的过滤。如果在数据库连接文件(如conn.asp)后加入程序代码,则可以实现整站的变量过滤,从而达到防注入的效果。
好了,下面我们先来看变量过滤部分的代码:
‘——–定义部份——————
Dim Fy_Post,Fy_Get,Fy_In,Fy_Inf,Fy_Xh,Fy_db,Fy_dbstr
‘自定义需要过滤的字串,用 “枫” 分隔
Fy_In = “‘枫;枫and枫exec枫insert枫select枫delete枫update枫count枫*枫%枫chr枫mid枫master枫truncate枫char枫declare”
‘———————————-
%>

<%
Fy_Inf = split(Fy_In,”枫”)
‘——–POST部份——————
If Request.Form<>”” Then
For Each Fy_Post In Request.Form

For Fy_Xh=0 To Ubound(Fy_Inf)
If Instr(LCase(Request.Form(Fy_Post)),Fy_Inf(Fy_Xh))<>0 Then
‘——–GET部份——————-
If Request.QueryString<>”” Then
For Each Fy_Get In Request.QueryString

For Fy_Xh=0 To Ubound(Fy_Inf)
If Instr(LCase(Request.QueryString(Fy_Get)),Fy_Inf(Fy_Xh))<>0 Then
这段代码中定义了对“’”“and”等常用注入变量的过滤,如果觉得过滤不够或太多可自行增减字符。很明显,只要通过get或post向服务器提交的数据中包含被过滤字符,都会被程序禁止。这就导致了一个问题,如果是在论坛的数据库连接文件后加入程序代码,发贴时只要贴子内容包括被过滤的字符就会被禁止掉。根据默认的过滤内容看来,如果发帖子内容为英文似乎是几乎无法发表的。另外,在定义论坛风格时有时会要用一些特殊字符(如百分号“%”)如果这些特殊字符被过滤的对象,那么整个论坛就不能正常运行了。对上面提到的问题,我用dvbbs做过测试,结果与我猜想的是完全一致的。
解决上述问题的方法是只在需要过滤的文件中防注入连接语句。但这样工作量比较大,而且一般站长是不知道什么文件需要过滤的。因此我的建议是把过滤代码加到conn.asp后,然后再建一个不包含过滤代码的connl.asp,把肯定不需要过滤且过滤代码对本文件运行有影响的文件连接到conn1.asp,但要注意两个数据连接文件的基本内容要保持一致。另外,在风格设置中最好不要用到过滤的字符,确实要用到的可在防注入程序中删掉对该字符的过滤。
上面讲的是防注入程序对站点运行的影响,并不能造成什么危害。其实,真正的危害来自数据记录部分,我们来看这部分的代码:
”——–写入数据库——-头——–
Fy_dbstr=”DBQ=”+server.mappath(“SqlIn.mdb”)+”;DefaultDir=;DRIVER={Microsoft Access Driver (*.mdb)};”
Set Fy_db=Server.CreateObject(“ADODB.CONNECTION”)
Fy_db.open Fy_dbstr
Fy_db.Execute(“insert into SqlIn(Sqlin_IP,SqlIn_Web,SqlIn_FS,SqlIn_CS,SqlIn_SJ) values(‘”&Request.ServerVariables(“REMOTE_ADDR”)&”‘,'”&Request.ServerVariables(“URL”)&”‘,’GET’,'”&Fy_Get&”‘,'”&replace(Request.QueryString(Fy_Get),”‘”,”””)&”‘)”)
Fy_db.close
Set Fy_db = Nothing
‘——–写入数据库——-尾——–

Response.Write “<Script Language=&#106avascript>alert(‘枫网SQL通用防注入系统提示↓\n\n请不要在参数中包含非法字符尝试注入!\n\nHTTP://WwW.WrSkY.CoM 系统版本:V2.0(ASP)完美版’);</Script>”
Response.Write “非法操作!系统做了如下记录↓<br>”
Response.Write “操作IP:”&Request.ServerVariables(“REMOTE_ADDR”)&”<br>”
Response.Write “操作时间:”&Now&”<br>”
Response.Write “操作页面:”&Request.ServerVariables(“URL”)&”<br>”
Response.Write “提交方式:GET<br>”
Response.Write “提交参数:”&Fy_Get&”<br>”
Response.Write “提交数据:”&Request.QueryString(Fy_Get)
Response.End
End If
Next
Next
End If
‘———————————-
这段代码的作用是对攻击者的信息及动作记录,以便我们采取必要的应对措施。从代码中可以看出程序分别对攻击者的IP,提交地址,提交内容等进行了记录,但这里明显有几处漏洞:
一、未对频繁的攻击进行处理。也就是说,无论我们怎么提交法数据,都会被程序记录,这样一来,将很可能导致恶意攻击的dos攻击。对此我做了一个试验。我在某个被保护文件的url后提交下列语句:and (select top l asc(mid (username,l,l)) from admin)>0,在提交过程中用按键精灵来记录,然后自动重复提交。不一会,数据库大小就发生了显著变化(如图1、2)。可以想象,如果用朔雪等工具开多线程提交,dos是绝对不成问题的。
二、记录数据长度未做截断。这是我在对防注入程序影响论坛运行的测试中发现的。如图3所示,如果发帖内容中包含被过滤字符时,帖子内容会被完全记录到数据库中。一般的论坛或文章系统对发表文章的长度都是限定的,但SQL通用防注入程序并未对此做出限制。如果攻击者在被保护文件的url后提交一段超长的内容,很可能会导致程序的崩溃。因为危害较大,我没有试验,但我提交长达100K的内容却是被照常记录的。
三、数据内容的转换及爆库问题。从代码中看,程序对非法提交的数据是未经转换就完全直接记录到数据库中的。也就是说,无论你提交什么只要包含被过滤的内容程序就会把你提交的所有内容进行记录。这个问题本来是并无大碍的,但某些站长为了“安全”起见,喜欢把mdb文件一律改为asp后缀的。再加上防注入程序的数据库中只有一个表,我们就可以通过在被保护文件url后直接写入数据库获得webshell了,在测试过程中,我们把sqlin.mdb改为sqlin.asp,然后在被保护文件的url后输入了一个冰浪子微型ASP后门。用冰狐客户端进行连接后成功获得wedshll。
因为这种获取webshell的方法需要确定对方的数据库是以ASP形式运行的,并且知道数据路径,所以我们必须想办法得到这个数据库的路径。一般情况下,我们可以直接猜数据库路径,但其实这个路径是可以暴出来的,纵观整个防注入程序,并没有发现什么防爆库的语句,所以我们只须直接访问或用%5C大法就能爆出这个数据库了.而如果是把程序代码直接放到数据库连接文件后的话,由于数据连接文件一般都包含防爆语句,我们就不能爆出数据库的地址了。
上面说的都是数据记录过程中的问题,有能力的站长可以自己动手修补相关漏洞,比如对大量重复提交法数据的IP自动屏蔽等。其实,我们完全可以去掉数据记录部分代码,这样并不影响对变量的过滤,而且既使记录了攻击者的信息作用也不是很大的。所以我建议最好还是去掉这段代码,这样一来所有