防注入攻击指南

作者: 风清扬 出处: E代V4
近段时间以来的网络攻击似乎多了起来,很多站点无故被黑甚至换掉首页。绝大多数站点被攻击的原因大都是由于站点程序上的漏洞,由攻击者得到WebShell后进而提升权限得到服务器主机权限。然而得到WebShell的途径也就集中到SQL Injection的攻击手法上。什么是SQL 注入攻击呢?来自官方的诠释:当应用程序使用输入内容来构造动态 SQL 语句以访问数据库时,会发生 SQL 注入攻击。如果代码使用存储过程,而这些存储过程作为包含未筛选的用户输入的字符串来传递,也会发生 SQL 注入攻击。SQL 注入可能导致攻击者能够使用应用程序登录在数据库中执行命令。如果应用程序使用特权过高的帐户连接到数据库,这种问题会变得很严重。换句话说:SQL 注入攻击利用易受攻击的数据访问代码,并允许攻击者在数据库中执行任意命令。如果应用程序使用数据库中不受限制的帐户,由于攻击者可以更自由地执行查询和命令,因此受到的威胁会更大。值得注意的是,传统的安全措施(如使用 SSL 和 IPSec)不能防止 SQL 注入攻击。


使数据访问代码容易受到 SQL 注入攻击的常见漏洞包括:本文转载出处E代时光E3i5.com

· 弱输入验证

· 在不使用类型安全的参数时动态构造 SQL 语句

· 使用特权过高的数据库登录

要应对 SQL 注入攻击,请务必注意:

· 限制和净化输入数据

· 使用类型安全的 SQL 参数进行数据访问。这些参数可以与存储过程一起使用,也可以是动态构造的 SQL 命令字符串。参数执行类型和长度检查,并同时确保注入数据库中的代码被视为文本数据(而非可执行语句)本文转载出处E代时光E3i5.com

· 使用在数据库中具有有限权限的帐户。理想情况下,只应向数据库中的选定存储过程授予执行权限,且不提供直接的表格访问权限

· 验证输入内容的类型、长度、格式和范围。如果您不希望获得数值,则不要接受它们。应该考虑输入内容来自何处。如果它来自受信任源,而且您知道已针对该来源执行过彻底的输入验证,则可以选择在数据访问代码中忽略数据验证。如果数据来自不受信任源或者用于深层防御,则数据访问方法和组件应该验证输入。
综上所述。

如何很好的预防SQL Injection攻击就成了现在安全防护的一个重点:本文转载出处E代时光E3i5.com

由于ASP的易学性和普遍性,很多站点都选择了使用ASP语言来构建自己的Web站点。ASP语言为脚本级编程语言,是以VBScript或JAVAScript。更多的站点选择了VBScript脚本作为编写的基础。然而很不幸的一点是VBScript对异常的捕捉(Debug)和数据类型的声明要求都相对JAVAScript要宽松得很多,没有强制要求,这样带来了方便也带来的隐患。(由于一些程序员的习惯,在使用VBScript编写ASP程序时常常忽略了对异常的捕捉(Debug)和数据类型的声明)所以在防止WEB注入攻击的方面就显得"心有余,而力不足"。回到我们的话题:谈起SQL Injection,我们首先想到的是寻找注入点。很多情况下Web方式的注入都是以ASP request 对象 为主。

quote: 例(1): http://target/index.asp?id=10


杜绝SQL 注入式攻击的第一步就是采用各种安全手段监控来自 ASP request 对象 (Request、Request.QueryString、Request.Form、Request.Cookies和 Request.ServerVariables) 的用户输入,以确保 SQL 指令的可靠性。像其他一些来自 ASP request 对象 (Reques、Request.QueryString、Request.Form、Request.Cookies和 Request.ServerVariables) 的用户输入的攻击方法的方法,大致都集中在脚本期望的输入变量是数字变量 (ID) 上(如例1),当然我们不能只看数字变量:本文转载出处E代时光E3i5.com

quote: 例(2): http://target/index.asp?username=风清扬


如例(2)中所引用的变量是以字符串变量传递。
通过URL传递变量的方式大概就以以上两种方式传递。第一,为数字变量;第二,为字符串变量。SQL Injection漏洞的出现,主要原因在于程序员的疏忽和大意,未采取过滤或是过滤不严密都会留给攻击者攻击的途径。下面就具体的介绍一下如何防范:
· 主动防护本文转载出处E代时光E3i5.com
何为主动防护?主动防护是指并非去对非法字符串进行过滤,而是主动的给出字符串输入范围来防止SQL Injection的攻击。很多站点的程序上都是以对来自 ASP request 对象的过滤上入手,仅仅被动的对一些已知的攻击字符进行过滤。比如以下程序:程序块(1)

quote: function HTMLEncode(Str)


Str=replace(Str,";",";")

Str=server.htmlencode(Str)

Str=replace(Str,"'","'")

Str=replace(Str,"--","--")

Str=replace(Str,"/","/")

Str=replace(Str,vbCrlf,"
")

HTMLEncode=Str

end function



以上程序块转自某论坛程序,其过滤了分号,<,>,单引号,--,/,&等特殊字符以及对软回车的转换。试想一下,如果以上的过滤有不严密的地方,那就是功亏于溃了。如程序块(1)对形如"../"的字符串没有过滤,在一些单表填写中可能会造成一些不必要的麻烦和隐患。如果我们采取主动防御的办法,以限制输入字符集为主,使用效率更高的正则表达式,如[0-9a-zA-Z]:程序块(2)

quote: 汉字的正则式:/[^/x00-/xff]/g


Email的正则式:/^[/w.-]+@([0-9a-z][/w-]+/.)+[a-z]{2,3}$/I

由数字、26个英文字母或者下划线组成的字符串:^/w+$

正确的URL:^[a-zA-z]+://(/w+(-/w+)*)(/.(/w+(-/w+)*))*(/?/S*)?$

正整数:^[0-9]*[1-9][0-9]*$

全数字格式:/[^/d]/g

应用:

Function CheckExp(patrn, strng)

Dim regEx, Match

Set regEx = New RegExp

regEx.Pattern = patrn

regEx.IgnoreCase = true

regEx.Global = True

Matches = regEx.test(strng)

CheckExp = matches

End Function

例子:


如果str为由数字、26个英文字母或者下划线组成的字符串,则返回True,否则返回False。



使用主动的限制输入的方式来限制字符的输入类型将对危险字符的过滤的效率上有很大的提高,相对的安全性也大大提高了。仅仅过滤非法的字符,HU~谁知道究竟哪些字符在哪种情况下属于非法字符呢?所以还是要主动,积极的去做过滤工作。补充一下,我们所提倡的限制输入字符集,而并非不让大家使用字符限制,在特定的条件下,过滤字符也会比限制输入范围要好得多。大家要学会灵活运用。

· 数据库的查询方式本文转载出处E代时光E3i5.com
发现有很多站点进行数据库查询的时候,还是使用rs.eof 或rs.bof作为查询结果的判断。RS(游标)的eof和bof属性分别表示为游标在数据末端或数据首端,所表示的意思为没有查找到相应的数据。大多数站点对用户登陆,用户注册等过程的对数据库现有数据的查询时,都采用的以下的方式:程序块(3)

quote:




如程序块(3)显示的程序段,如果变量username和password由于程序员的疏忽或其他原因没有进行过滤或是过滤不严密,将会造成SQL Injection的漏洞。只是使用rs.bof or rs.eof作为数据库数据遍历的依据是很不安全的。从安全角度出发,我们应当使用如下的方式作为判断的依据:程序块(4)本文转载出处E代时光E3i5.com

quote:




有了if rs("username")=username then这个语句的存在(红色部分),使得验证时不得不多了一次检测,不仅仅只是满足SQL查询语句的正确性,也使得查询得到的数据与输入的数据相一致时才给出正确的判断。

· 数据库其他方式查询的检测
想必很多站点问题出现都是在这个环节,其实这个环节的问题是最多的也是最容易解决的。很多程序员由于没有良好的编程习惯,只实现功能,并不注意其程序的安全性,或者对更细节的东西没有注意到,这也是引起站点程序被攻击的一个方面。具体的问题主要集中在以下的几个方面:
1. 查询的返回字段值
很多朋友都喜欢使用以下的语句进行查询工作,如程序块(5)

quote: Sql="select * from [user] where uid="&id&" order by uid desc"


简单看来这句语句如果在数字变量 (ID)上有限制的话,整个语句可能是很安全的。但是使用select * 来查询全部字段有些时候会带来更多的安全问题。我很推荐,尤其是个人编写的程序中尽量少的使用select *来对数据表中的字段进行查询,做到将要用哪个字段就查询哪个字段的要求。
2. 数字格式的变量检测本文转载出处E代时光E3i5.com
这个应该是ASP程序中使用最多的变量类型,很多人都觉得使用字符串型的变量在过滤的时候很难办,所以很多都是使用数字ID来作为变量的传递。而往往过多的使用却使程序员很容易忘记某个数字ID是否做过变量类型的检测。在前面我们提到过,VBScript脚本对数据类型的声明没有其他语言的的严密。在Java中定义一个新的变量首先就是定义变量的数据类型如:


quote: 1. String a="good day";


2. Int a=3;

3. Public static string MadeThisExample(string pwd, int sold)

{

String key=string.Concant(pwd, sold);

String result=LoopAddr("MADETHISOUT",key);

Return result;

}



有了严格的数据类型,我们就可以根据不同的数据类型做不同的过滤或者是异常的捕捉。然而ASP安全在这一点上是最没有优势的。如以下的ASP程序片段 :本文转载出处E代时光E3i5.com


quote: Dim str_a,int_b


Str_a=request("str_a")

Int_b=request("int_b")


以上的程序片段中我们可以看到我们预期想得到的字符串str_a,整形数字int_b,然而在ASP可以定义无数据类型的数据,这就使得程序的编写者不得不注意要强制一些变量的数据类型,并做异常捕捉。比如整形变量int_b作为整形的判断:

quote: Dim int_b


Int_b=cint(request("int_b"))


这样以来,int_b被强制为整形变量,当int_b为非整形时,程序会产生错误:"字符类型不匹配"
我们在对数字变量进行判断的时候一般都采用以下的几个函数来进行判断:

quote: Cint,Clng,IsNull,IsEmpty, IsNumeric等等


在我们常用的程序中,以上几个判断函数就足够了,对所有request对象数据类型为整形的变量进行强制整形的操作。甚至可以写出一个通用的校验函数来进行全局校验。关于校验函数,这里就不提了,在网上有很多朋友写出过一些过滤函数,大家可以搜索一下作为借鉴。

3. 字符串格式的校验本文转载.出处E代时光E3i5.com
使用字符串作为变量就没有类似象整形变量判断的函数咯,是不是对这样的变量感到很棘手。在无法变通的情况下只能去硬着头皮去进行死板的非法字符的过滤,感觉应该过滤的东西太多了,更郁闷的是要过滤的字符还有用户在使用,这样的情况怎么办?都怪自己当初写程序的时候没注意,等发现问题的时候已经有不少用户的资料中存在即将要屏蔽的字符了。其实类似字符串格式的变量进行校验的方式也和前面所说过的方法差不多。
(一)采用给定字符集合的方式,只能输入指定的字符。具体方法请查看程序块(2)
(二)采用游标数据校验,方法类似用户登陆的写法。例如:程序块(6)

quote: Dim sql,rs


Dim type

Type=request("stype")

sql="select articleid,articletypes,articletitle, articlewrter, Adddate from [article] where articletypes ='"&type&'" order by articleid desc"

Set rs=Conn.Execute(sql)

if not(rs.eof or rs.bof) then

if rs("articletype")=type then

文章列表操作

else

变量错误操作

end if

end if


如程序块(6)所示,不论字符串变量的内容是什么,只要不能通过if rs("articletype")=type then的检测都被视为这个字符串变量的内容是非法的。如此操作将比单一的去过滤非法的字符要好得多。鬼晓得不定哪一天又出现了什么新的注入方法,即使屏蔽掉一些特殊字符也可以利用其他方法进行注入的。

4. 变量的长度后台检测本文转载出处E代时光E3i5.com
为什么还要在已经检测过的程序后面加长度检测呢?(呵呵,有些朋友还是不放心嘛。开玩笑De)这也取决于程序需要,前台脚本级的限制也只是局限于一个客户端的过滤,作为攻击者完全可以通过某些手段来突破客户端限制,那么防范这样的攻击,我们只能从服务端程序入手,对单表限制的长度再加一次检测,其一可以防止数据写入数据库时由于字符串长度过大而写数据库失败的问题;其二可以更有效的防范SQL Injection攻击。限制变量长度:程序块(7)

quote: 我们使用len() 函数来判断字符串的长度,对于超过长度要求的或重新付值或返回错误信息,并终止程序向下进行。如:






5. 防止远程注入的问题
这个情况真的是容易让人遗忘。包括动网论坛也出现如此情况哦,比如文件上传的数据处理文件没有对远程信息和不受信任来源的信息进行校验,再加上校验程序上的一点点小BUG,服务器上的一点点安全配置问题,整个网站就被"黑"了。相信很多朋友都身受其害,不光光是论坛程序,其他一些站点内的数据处理程序,既没有权限验证,也没有对不信任区域的请求加以过滤,这就使得我不知道密码也能改你站点页面的情况时有发生了。要提醒一点的是,很多朋友怕自己的站点被黑,将使用的免费程序的后台登陆地址稍做修改就以为万事大吉了,尤其是登陆页面和数据处理页面不在同一页面的,而且数据处理页面没有对不信任区域的请求加以过滤的,即使你改过登陆口,攻击者还是可以伪造数据进行登陆。尤其是一些非URL上的注入攻击,比如单表上的SQL注入,仅仅做页面单表的脚本级过滤,而攻击者在发现数据处理页面上没有对不信任区域的请求加以过滤时,一般都会在本地伪造页面进行非法语句的提交,那是防不胜防哦。以下再次给出防止远程注入的代码:程序块(8)本文转载出处E代时.光E3i5.com

quote:




· 有关数据安全的一点说明
还是要提一下,有经济能力使用SQL数据库+服务器整机的朋友注意,数据库帐户的开设权限要尽量接近理想情况下,只应向数据库中的选定存储过程授予执行权限,且不提供直接的表格访问权限,以及对服务器一些特殊的命令和文件进行删除或改名。
使用ACCESS数据库的用户,应该注意保护CONN.ASP文件的安全性,最好使用异常捕捉将数据库连接的错误信息屏蔽掉。以防止敏感信息的泄露。如:程序块(9)

quote:




另外使用ACCESS数据库的朋友要注意数据库的防下载防护,步骤为:
1. 使用ASP程序向数据库写入OLE数据,写入内容为<%
2. 将数据库改名为ASA结尾的文件,由于IIS服务器对ASA文件的保护要比ASP文件更高,所以我们选择ASA文件作为ACCESS数据库文件的结尾扩展名。
3. 在改好的数据库名中加入一个#号,目的是防止其他程序出现SQL Injection问题时,阻止"跨库查询"的操作。

最后更加不要忘记将站点程序的安装文件删除,否则被"黑"是应该滴,因为这样才会长记性嘛。


· 后记
看到近来网络上的不平静,感觉这篇文章写出来能对各位站长有所帮助或是提醒。抓紧时间看看你的站上的程序,说不定哪个不起眼的页面上就存在着以上的问题。HU~更加担忧的是国内的一些门户站点也存在着类似的问题,甚至一些安全公司,国家级机构的站点。形式似乎迫在眉睫,管理员们该工作了,举手之劳。本文转载出处E代时光E3i5.com
有什么疑问的朋友请到www.e3i5.com询问。谢谢!

参考文献:
1. http://www.securiteam.com/securityreviews/5DP0N1P76E.html
2. http://msdn.microsoft.com/msdnmag/issues/04/09/SQLInjection/default.aspx
3. http://www.4guysfromrolla.com/webtech/061902-1.shtml
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值