无列名bypass

bypass information_schema

一般而言在常规的sql注入中,我们在查询表名时,都会使用information_schema这个库,但是waf都会把这个给禁了,所以我们要尝试其他方法(看了大佬的wp,进行总结)

bypass之前先了解下information_schema这个库的作用:

information_schema简单来说无非就是获取到table_schema,table_name,column_name

1
简单来说,这个库在mysql中就是个信息数据库,它保存着mysql服务器所维护的所有其他数据库的信息,包括了数据库名,表名,字段名等。

Mysql5.7的新特性

1
由于performance_schema过于发杂,所以mysql在5.7版本中新增了sys schemma,基础数据来自于performance_chema和information_schema两个库,本身数据库不存储数据。

sys.schema_auto_increment_columns
可以知道的是,我们在设计数据库时,比如说id这样的数据都是呈自增的的数字,那么我们可以发现一个注入中在mysql默认情况下可以替代information_schema库的方法

1
chema_auto_increment_columns,该视图的作用简单来说就是用来对表自增ID的监控。

比如说建立了security和fortest这两个库,来熟悉下shcema_auto_increment_columns的结构组成还有特性
# fortest库

data 表存在自增id

no_a_i_table 表不存在自增id

test 表存在自增id

# security库

emails,referers,uagents,users

图片

可以发现,fortest库中的no_a_i_table并不在这里存在,然而其他非系统库的表信息全部在这里。根据前面介绍的schema_auto_increment_columns视图的作用,也可以发现我们可以通过该视图获取数据库的表名信息,也就是说找到了一种可以替代information_schema在注入中的作用的方法

那如果没有设置自增的数据呢?翻阅文档可以发现另外一个库

schema_table_statistics_with_buffer,x$schema_table_statistics_with_buffer

1
查询表的统计信息,其中还包括InnoDB缓冲池统计信息,默认情况下按照增删改查操作的总表I/O延迟时间(执行时间,即也可以理解为是存在最多表I/O争用的表)降序排序,数据来源:performance_schema.table_io_waits_summary_by_table、sys.x$ps_schema_table_statistics_io、sys.x$innodb_buffer_stats_by_table

sys.schema_table_statistics_with_buffer
可以看到,在上一个视图中并没有出现的表名在这里出现了。

图片

# sys.x$schema_table_statistics_with_buffer.

图片

上面的库都可以让我们获取数据库中表名信息,但并没有找到类似information_schema中的columns,也就是目前我们并不能获取数据

join

常见ctf思路,利用join进行无列名注入

join…using(xx)

以上文的环境为例,这里waf会把information_schema完全过滤

1
2
3
4
5
6
# schema_auto_increment_columns

?id=-1' union all select 1,2,group_concat(table_name)from sys.schema_auto_increment_columns where table_schema=database()--+

# schema_table_statistics_with_buffer
?id=-1' union all select 1,2,group_concat(table_name)from sys.schema_table_statistics_with_buffer where table_schema=database()--+

其他的都是类似的
获取列名

1
2
3
4
5
6
# 获取第一列的列名

?id=-1' union all select*from (select * from users as a join users b)c--+

# 获取次列及后续列名
?id=-1' union all select*from (select * from users as a join users b using(id,username))c--+

无列名注入

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

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

假设我们通过暴力破解或者其他手段得到了表名,但是没有列名

1
在 information_schema 中,除了 SCHEMATA、TABLES、COLUMNS 有表信息外,高版本的 mysql 中,还有 INNODB_TABLES 及 INNODB_COLUMNS 中记录着表结构。

使用条件&方法
无列名注入主要是适用于已经获取到数据表,但无法查询列的情况下,在大多数 CTF 题目中,information_schema 库被过滤,使用这种方法获取列名。

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

不使用表名查询

正常的SQL查询:

1
select * from `admin`;

图片

其中列名为id,name,password,使用union查询

1
select 1,2,3 union select * from admin;

图片

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

1
select `3` from (select 1,2,3 union select * from admin)a;

图片

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

当然,多数情况下,会被过滤。当 不能使用的时候,使用别名来代替

1
select b from (select 1,2,3 as b union select * from admin)a;

图片

同时查询多个列:

1
select concat(`2`,0x2d,`3`) from (select 1,2,3 union select * from admin)a limit 1,3;

图片

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