被血虐的一场比赛的记录,主要考点是如何在过滤了各种关键词的情况下查询一个复杂列名(极长也无法爆破)
题目过滤了information,innodb_index_stats,table等关键词,无法从库中直接查询列名
同时过滤了union,无法通过无列名注入来获取flag
了解到了一种新的注入姿势
使用这个数据库,假设我们不知道password这个列名
payload:
select * from(select * from testtable a join testtable b using(id,usename))c;
接下来分析一下结构:
首先是使用的SQL join连接和using简化连接
select * from testtable a join testtable b using(id,usename);
意思是testtable连接testtable,以id和usename列为属性列
testtable后面的a和b是别名,如果不使用别名会出现报错,估计是mysql不允许两个名字完全相同的数据库连接,如果一样就没法在后面加on a.id=b.id and a.usename=b.usename;这种了
select * from testtable join testtable using(id,usename);
之后是一个派生表和别名
SQL的别名很神奇,跟在后面就行
select * from testtable a;
等同于
select * from testtable as a;
而派生表就是把查询结果作为一个表来处理,而派生表必须有一个别名
当派生表没有别名直接使用时
select * from (select * from testtable);
正确的用法:
select * from (select * from testtable)a;
select * from (select * from testtable)as a;
而派生表还有个特性就是不允许有重复的列,如果有则会报错并告知是哪个列重复了,方便修改语句,所以利用这个特性,我们可以得到数据库的列名
由上面可知我们在执行
select * from testtable a join testtable b using(id,usename);
后得到的派生表password列是重复的,为它设置别名时会有
select * from(select * from testtable a join testtable b using(id,usename))c;
得到列名password