ASP/SQL 注入天书

2015 年 7 月 22 日3500

引言

随着 B/S 模式应用开发的发展,使用这种模式编写应用程序的程序员也越来越多。但是由于这个行业的入门门槛不高,程序员的水平及经验也参差不齐,相当大一部分程序员在编写代码的时候,没有对用户输入数据的合法性进行判断,使应用程序存在安全隐患。用户可以提交一段数据库查询代码,根据程序返回的结果,获得某些他想得知的数据,这就是所谓的 SQL Injection,即SQL注入。

SQL注入是从正常的 http://www.zjjv.com/ 开始(注:本文发表前已征得该站站长同意,大部分都是真实数据)。

在网站首页上,有名为“ IE 不能打开新窗口的多种解决方法”的链接,地址为:http://http://www.zjjv.com///showdetail.asp?id=49,我们在这个地址后面加上单引号’,服务器会返回下面的错误提示:

Microsoft?JET?Database?Engine?错误?80040e14?
字符串的语法错误?在查询表达式?ID=49?中。?
/showdetail.asp,行8

从这个错误提示我们能看出下面几点:

从上面的例子我们可以知道,SQL注入的原理,就是从客户端提交特殊的代码,从而收集程序及服务器的信息,从而获取你想到得到的资料。

第二节、判断能否进行SQL注入

看完第一节,有一些人会觉得:我也是经常这样测试能否注入的,这不是很简单吗? 其实,这并不是最好的方法,为什么呢?

首先,不一定每台服务器的 IIS 都返回具体错误提示给客户端,如果程序中加了 cint(参数) 之类语句的话,SQL注入是不会成功的,但服务器同样会报错,具体提示信息为处理 URL 时服务器上出错。请和系统管理员联络。

其次,部分对SQL注入有一点了解的程序员,认为只要把单引号过滤掉就安全了,这种情况不为少数,如果你用单引号测试,是测不到注入点的

那么,什么样的测试方法才是比较准确呢?答案如下:

这就是经典的 1=1、1=2 测试法 了,怎么判断呢?看看上面三个网址返回的结果就知道了,可以注入的表现:

不可以注入就比较容易判断了,1 同样正常显示,2 和 3 一般都会有程序定义的错误提示,或提示类型转换时出错。

当然,这只是传入参数是数字型的时候用的判断方法,实际应用的时候会有字符型和搜索型参数,我将在中级篇的“SQL注入一般步骤”再做分析。

第三节、判断数据库类型及注入方法

不同的数据库的函数、注入方法都是有差异的,所以在注入之前,我们还要判断一下数据库的类型。一般 ASP 最常搭配的数据库是 Access 和 SQLServer,网上超过 99% 的网站都是其中之一。

怎么让程序告诉你它使用的什么数据库呢?来看看: SQLServer 有一些系统变量,如果服务器 IIS 提示没关闭,并且 SQLServer 返回错误提示的话,那可以直接从出错信息获取,方法如下:

接着,将查询条件替换成SQL语句,猜解表名,例如:

第三节、中文处理方法

在注入中碰到中文字符是常有的事,有些人一碰到中文字符就想打退堂鼓了。其实只要对中文的编码有所了解,“中文恐惧症”很快可以克服。 先说一点常识:

以上 6 点是我研究 SQLServer 注入半年多以来的心血结晶,可以看出,对 SQLServer 的了解程度,直接影响着成功率及猜解速度。在我研究 SQLServer 注入之后,我在开发方面的水平也得到很大的提高,呵呵,也许安全与开发本来就是相辅相成的吧。

第二节、绕过程序限制继续注入

在入门篇提到,有很多人喜欢用’号测试注入漏洞,所以也有很多人用过滤’号的方法来“防止”注入漏洞,这也许能挡住一些入门者的攻击,但对SQL注入比较熟悉的人,还是可以利用相关的函数,达到绕过程序限制的目的。

在“SQL注入的一般步骤”一节中,我所用的语句,都是经过我优化,让其不包含有单引号的;在“利用系统表注入SQLServer数据库”中,有些语句包含有’号,我们举个例子来看看怎么改造这些语句:

简单的如where xtype='U',字符U对应的ASCII码是85,所以可以用where xtype=char(85)代替;如果字符是中文的,比如where,可以用where name=nchar(29992)+nchar(25143)代替。

第三节、经验小结

防范方法

SQL注入漏洞可谓是“千里之堤,溃于蚁穴”,这种漏洞在网上极为普遍,通常是由于程序员对注入不了解,或者程序过滤不严格,或者某个参数忘记检查导致。在这里,我给大家一个函数,代替 ASP 中的 Request 函数,可以对一切的 SQL 注入 Say NO,函数如下:

Function SafeRequest(ParaName,ParaType)
? 'ParaName:参数名称-字符型
? 'ParaType:参数类型-数字型(1表示以上参数是数字,0表示以上参数为字符)
? Dim ParaValue
? ParaValue=Request(ParaName)
? If ParaType=1 then
??? If not isNumeric(ParaValue) then
????? Response.write "参数" & ParaName & "必须为数字型!"
????? Response.end
??? End if
? Else
??? ParaValue=replace(ParaValue,"","")
? End if
? SafeRequest=ParaValue
End function

文章到这里就结束了,不管你是安全人员、技术爱好者还是程序员,我都希望本文能对你有所帮助。 (作者:小竹

注:自己玩弄 ASP 有大把时日了,对 SQL 注入还是一知半解。多亏了这篇文章,令人一目了然。之后对自己的网站试了一下,果然存在 SQL 注入漏洞,借助一个这方面的小工具居然非常轻易就可以拿到管理员账号及密码(MD5 过的)。嘿嘿,最近没什么时间,没办法,也就知而不改了。那位有 MD5 破解效率高点的工具,可以跟我交流交流啊。呵呵。文章写得非常不错,推荐大家看看。最后,祝各位新春快乐,万事如意!

0 0