一次利用sql通用防注入系统的经历
[ 2008-02-27 11:56:54 | 作者: dklkt ]
前两天,一个跟我比较有关系的网站被操了.虽然看得出来,那个自称的所谓的hacker只拿到了网站后台的权限,改改网站的标题,发发文章而已.webshell都没有拿到。然后我看了那个站,最简单最基本的sql注入而已,管理员的密码是弱口令,md5加密.一点技术含量都没有.也不知道他是怎么想的.
过了2天,发现管理员还没有动静,想想那网站现在也是没什么人在管了。所以进去逛了下,发现是虚拟主机,没有上传组件,难怪那个自称的hacker没拿到webshell。后来又看了下,fso功能正常,后台有数据库备份的地方,又有css文件手动编辑的功能,所以先编辑css文件往里面插入一句话木马,然后通过备份改成asp文件。webshell就拿到了。
发现网站里面乱七八糟,注入点一大堆,几乎所有的参数都没有过滤。汗~~~
本想给它改改的,后来发现工作量太大,干脆搞个通用防注入算了。
这里用的是Neeao的“SQL通用防注入系统3.1 最终纪念版”。在此表示感谢!另外顺便说下,先前用过“3.1 β版”发现有部分缺陷,过滤貌似会漏掉,所以大家用的时候也建议用最终版。
于是在网站的conn.asp文件里加上文件包含,这样就整站都过滤了。
下面给大家看看部分防注入的代码吧。
所以我将这条语句If Request.Form<>"" Then StopInjection(Request.Form)删掉了。这样就会缓解这个问题。也就是说,对表单都不过滤了。
暂时先写到这吧。
当然,网站的安全性在系统设计的时候就应该考虑,如果等到之后再来修补,那将会是一件非常麻烦的事情。这件事也给了我很大的启发。
最后再次感谢Neeao的这个小工具,给我省了不少力。
===================无===敌===分===割===线=====================
看到很多朋友留言问怎么解决sql注入的问题。因此打算把本文更新下。
最近帮一个网站修补sql注入漏洞,用了下面的代码。大家可以拿去用。用到的是正则表达式过滤。只需要在一个公共包含的文件里添加下面的代码即可。
过了2天,发现管理员还没有动静,想想那网站现在也是没什么人在管了。所以进去逛了下,发现是虚拟主机,没有上传组件,难怪那个自称的hacker没拿到webshell。后来又看了下,fso功能正常,后台有数据库备份的地方,又有css文件手动编辑的功能,所以先编辑css文件往里面插入一句话木马,然后通过备份改成asp文件。webshell就拿到了。
发现网站里面乱七八糟,注入点一大堆,几乎所有的参数都没有过滤。汗~~~
本想给它改改的,后来发现工作量太大,干脆搞个通用防注入算了。
这里用的是Neeao的“SQL通用防注入系统3.1 最终纪念版”。在此表示感谢!另外顺便说下,先前用过“3.1 β版”发现有部分缺陷,过滤貌似会漏掉,所以大家用的时候也建议用最终版。
于是在网站的conn.asp文件里加上文件包含,这样就整站都过滤了。
下面给大家看看部分防注入的代码吧。
<%
'--------定义部份------------------
Dim N_Post,N_Get,N_In,N_Inf,N_Xh,N_db,N_dbstr,Kill_IP,WriteSql
Dim aApplicationValue
If IsArray(Application("Neeao_config_info"))=False Then Call PutApplicationValue()
aApplicationValue = Application("Neeao_config_info")
'获取配置信息
N_In = aApplicationValue(0)
Kill_IP = aApplicationValue(1)
WriteSql = aApplicationValue(2)
alert_url = aApplicationValue(3)
alert_info = aApplicationValue(4)
kill_info = aApplicationValue(5)
N_type = aApplicationValue(6)
Sec_Forms = aApplicationValue(7)
Sec_Form_open = aApplicationValue(8)
'安全页面参数
Sec_Form = split(Sec_Forms,"|")
N_Inf = split(N_In,"|")
If Kill_IP=1 Then Stop_IP
If Request.Form<>"" Then StopInjection(Request.Form)
If Request.QueryString<>"" Then StopInjection(Request.QueryString)
If Request.Cookies<>"" Then StopInjection(Request.Cookies)
Function Stop_IP()
Dim Sqlin_IP,rsKill_IP,Kill_IPsql
Sqlin_IP=Request.ServerVariables("REMOTE_ADDR")
Kill_IPsql="select Sqlin_IP from SqlIn where Sqlin_IP='"&Sqlin_IP&"' and kill_ip=true"
Set rsKill_IP=killSqlconn.execute(Kill_IPsql)
If Not(rsKill_IP.eof or rsKill_IP.bof) Then
N_Alert(kill_info)
Response.End
End If
rsKill_IP.close
End Function
'输出警告信息
Function N_Alert(alert_info)
Dim str
str = "<"&"Script Language=JavaScript"&">"
Select Case N_type
Case 1
str = str & "window.opener=null; window.close();"
Case 2
str = str & "alert('"&alert_info&"Http:Www.Neeao.Com\n\nBy:Neeao');window.opener=null; window.close();"
Case 3
str = str & "location.href='"&alert_url&"';"
Case 4
str = str & "alert('"&alert_info&"');location.href='"&alert_url&"';"
end Select
str = str & "<"&"/Script"&">"
response.write str
End Function
'判断注入类型函数
Function intype(values)
Select Case values
Case Request.Form
intype = "Post"
Case Request.QueryString
intype = "Get"
Case Request.Cookies
intype = "Cookies"
end Select
End Function
'sql通用防注入主函数
Function StopInjection(values)
For Each N_Get In values
If Sec_Form_open = 1 Then
'response.write SelfName
For N_i=0 To UBound(Sec_Form)
'response.write SelfName
'response.write Sec_Form(N_i)
If Instr(LCase(SelfName),Sec_Form(N_i))> 0 Then
Exit Function
else
Select_BadChar(values)
End If
Next
Else
Select_BadChar(values)
End If
Next
End Function
Function Select_BadChar(values)
For N_Xh=0 To Ubound(N_Inf)
If Instr(LCase(values(N_Get)),N_Inf(N_Xh))<>0 Then
If WriteSql = 1 Then InsertInfo(values)
N_Alert(alert_info)
Response.End
End If
Next
End Function
'将注入记录记录到数据库函数
Function InsertInfo(values)
Dim ip,url,sql
ip = Request.ServerVariables("REMOTE_ADDR")
url = Request.ServerVariables("URL")
sql = "insert into SqlIn(Sqlin_IP,SqlIn_Web,SqlIn_FS,SqlIn_CS,SqlIn_SJ) values('"&ip&"','"&url&"','"&intype(values)&"','"&N_Get&"','"&N_Replace(values(N_Get))&"')"
'response.write sql
killSqlconn.Execute(sql)
killSqlconn.close
Set killSqlconn = Nothing
End Function
Function N_Replace(N_urlString)
N_urlString = Replace(N_urlString,"'","''")
N_urlString = Replace(N_urlString, ">", ">")
N_urlString = Replace(N_urlString, "<", "<")
N_Replace = N_urlString
End Function
sub PutApplicationValue()
dim infosql,rsinfo
set rsinfo=killSqlconn.execute("select N_In,Kill_IP,WriteSql,alert_url,alert_info,kill_info,N_type,Sec_Forms,Sec_Form_open from config")
Redim ApplicationValue(9)
dim i
for i=0 to 8
ApplicationValue(i)=rsinfo(i)
next
set rsinfo=nothing
Application.Lock
set Application("Neeao_config_info")=nothing
Application("Neeao_config_info")=ApplicationValue
Application.unlock
end Sub
'获取本页文件名
Function SelfName()
SelfName = Mid(Request.ServerVariables("URL"),InstrRev(Request.ServerVariables("URL"),"/")+1)
End Function
%>
从以上的代码可以看出,其实通用防注入的原理比较简单,就是把所有客户提交上来的东西都先检查一番,看看有没有sql注入常用到的关键字。如果有的话,采取相应的措施。不过,用这个防注入代码是会带来一个使用上的问题的,大家注意看这几句:If Request.Form<>"" Then StopInjection(Request.Form) If Request.QueryString<>"" Then StopInjection(Request.QueryString) If Request.Cookies<>"" Then StopInjection(Request.Cookies)特别是Request.Form那个,也就是说,假如管理员发表一篇文章中含有"and",";"等被过滤的关键字的话,那么也会被k掉。这么说,一篇英文文章根本就无法发表了。这个严重影响了网站的正常使用。
所以我将这条语句If Request.Form<>"" Then StopInjection(Request.Form)删掉了。这样就会缓解这个问题。也就是说,对表单都不过滤了。
暂时先写到这吧。
当然,网站的安全性在系统设计的时候就应该考虑,如果等到之后再来修补,那将会是一件非常麻烦的事情。这件事也给了我很大的启发。
最后再次感谢Neeao的这个小工具,给我省了不少力。
===================无===敌===分===割===线=====================
看到很多朋友留言问怎么解决sql注入的问题。因此打算把本文更新下。
最近帮一个网站修补sql注入漏洞,用了下面的代码。大家可以拿去用。用到的是正则表达式过滤。只需要在一个公共包含的文件里添加下面的代码即可。
'------------------------------------------------------------------------
'通用防SQL注入代码 by dklkt 2009.2
'------------------------------------------------------------------------
If Request.Form<>"" Then StopInjection(Request.Form)
If Request.QueryString<>"" Then StopInjection(Request.QueryString)
If Request.Cookies<>"" Then StopInjection(Request.Cookies)
Function StopInjection(values)
Dim L_Get, L_Get2, regEx
For Each L_Get In values
L_Get2 = values(L_Get)
Set regEx = New RegExp
regEx.IgnoreCase = True
regEx.Global = True
regEx.Pattern = "(\bselect\b|\band\b|'|;|\bor\b|\bxor\b|\bunion\b|\bexec\b|\binsert\b|\bdelete\b|\bupdate\b|\bcount\b|\bchr\b|\bmid\b|\bmaster\b|\btruncate\b|\bchar\b|\bdeclare\b)"
If regEx.Test(L_Get2) Then
Alert()
response.End()
End If
Set regEx = Nothing
Next
End Function
Sub Alert()
Dim str
str = "<"&"Script Language=JavaScript"&">"
str = str & "alert('由于您提交的内容可能包含危险字符,系统已经禁止本次提交,请求的IP已经被记录 \n\n请确保提交的内容中不包含:单引号|select|and|;|or|xor|union|exec|insert|delete|\nupdate|count|chr|mid|master|truncate|char|declare');history.back(-1);"
str = str & "<"&"/Script"&">"
response.write str
End Sub
[最后修改由 dklkt, 于 2009-02-24 22:44:00]

评论Feed: http://www.dklkt.cn/feed.asp?q=comment&id=81
引用链接: 


本文的目的在于讨论:通用防注入系统的缺点——对提交的表单也会检查,从而造成使用上的不便。
以下是一种过滤方法的提示。转自邪八。
--------------------
文章作者:勇敢的风 [E.S.T顾问团成员]
信息来源:邪恶八进制信息安全团队(www.eviloctal.com)以前没有限制大小写,现在加上了。
通用的弊端在上一层我已经说了,这里简单说说针对个别的过滤说一下
过滤sql注入时,我们应该过滤那些字段我们应该清楚,就是出现在sql语句中的变量,一般出现在SQL语句中的变量为搜索的时候,有的时候搜索数字,有些时候搜索文字,对于数字我们可以用判断该变量是不是数字即可,对于文字,用上面的代码即可。
代码说明:
if instr(str,w(j)) <> 0 then
找到sql注入后所作的处理
end if
用法,把这段代码放在读取数据库的那个文件,一般为Conn.asp
然后对出现在sql语句中的变量使用该函数即可,如:
sql_zr(request("key"))