尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

SQL注入绕过WAF实战:从原理到Payload构造的完整对抗指南

SQL注入绕过WAF实战:从原理到Payload构造的完整对抗指南
📅 发布时间:2026/6/26 6:12:51

1. 项目概述:当SQL注入遇上WAF

在Web安全领域,SQL注入(SQL Injection)和Web应用防火墙(WAF)就像一对永恒的“矛与盾”。作为一名长期在一线进行渗透测试和安全评估的从业者,我几乎每天都会遇到这对组合。很多刚入门的朋友,一看到WAF的拦截页面就头疼,觉得无计可施。但实际情况是,WAF并非铜墙铁壁,它更像是一个基于规则和模式的过滤器。理解它的工作原理,就能找到绕过它的方法。今天,我就结合自己多年的实战经验,系统性地拆解一下那些行之有效的SQL注入绕过WAF的技巧。这不仅仅是几个Payload的堆砌,更是一种对抗思路的建立,让你在面对防护时,能像解谜一样,找到那条隐藏的路径。

简单来说,这个“项目”的核心就是:在目标网站部署了WAF(如云WAF、硬件WAF或软件WAF模块)的情况下,如何通过精心构造的SQL注入语句,成功执行恶意查询并获取数据。它适合所有对Web安全感兴趣的朋友,无论是正在学习渗透测试的学生,还是需要评估自身应用安全性的开发者。通过本文,你将不仅学到“怎么做”,更能理解“为什么能这么做”,从而建立起主动防御和有效攻击的双重视角。

2. 核心对抗思路:理解WAF的运作与盲点

在开始具体技巧之前,我们必须先搞清楚对手。WAF绕过的本质是“规则对抗”。绝大多数WAF(尤其是基于正则表达式或关键字匹配的WAF)的工作流程可以简化为:截获HTTP请求 -> 解析请求参数 -> 与内置的恶意规则库进行匹配 -> 若匹配则拦截/告警,否则放行。

2.1 WAF的常见检测维度

WAF的检测并非单一维度,通常是一个组合拳:

  1. 关键字/模式匹配:这是最基础的一层。WAF维护了一个庞大的“黑名单”,包含union select、information_schema、sleep(、benchmark(、extractvalue(、updatexml(等敏感SQL关键字和函数。一旦请求中出现这些字符串,就可能被拦截。
  2. 语法/语义分析:高级WAF会尝试解析SQL语句的语法结构。例如,它可能检测不正常的括号嵌套、异常的运算符使用(如1‘ and ‘1’=’1中的逻辑)或语句结构的异常。
  3. 流量/行为异常检测:通过统计模型,检测异常请求频率、异常参数长度、非常规的HTTP方法等。例如,短时间内大量提交包含sleep()函数的请求,即使每次Payload都不同,也可能触发行为规则。
  4. 编码/混淆识别:WAF会尝试对URL编码、Unicode编码、十六进制编码等进行解码,然后再次进行规则匹配。

2.2 绕过的基本哲学:制造“差异”

我们的目标,就是制造WAF解析结果与数据库SQL引擎解析结果之间的“差异”。让WAF“看”到一个无害或无法识别的请求,而数据库“执行”的却是我们精心构造的恶意语句。这种差异主要通过以下几种方式实现:

  • 混淆:让恶意代码“看起来”不像恶意代码。例如,将关键字拆散、插入注释、使用非常规的空白字符。
  • 等效替换:用功能相同但写法不同的语法或函数来替代被拦截的关键字。
  • 利用解析差异:利用WAF解析器与数据库解析器在处理特定字符、编码、注释时的不同行为。
  • 资源耗尽/逻辑绕过:通过构造极其复杂的Payload,试图耗尽WAF的解析资源(如正则回溯),或者利用WAF规则逻辑的漏洞(如只检测第一个参数)。

理解了这些,我们再看具体技巧,就不会觉得是零散的“奇技淫巧”,而是有章可循的战术组合。

3. 字符级绕过:从最细微处着手

这是最基础,也往往最有效的第一层尝试。核心思想是干扰WAF的字符串匹配。

3.1 注释符的妙用

SQL注释(--,#,/*...*/)在绕过中扮演着“分隔符”和“扰乱器”的角色。

  • 拆分关键字:这是绕过union select拦截的经典方法。WAF的规则可能是/union[[:space:]]+select/i。我们可以用注释将其拆开:
    U/**/NION/**/SEL/**/ECT 1,2,3 --
    对于数据库,/**/被视为一个可忽略的注释,语句等价于UNION SELECT 1,2,3。但对于简单的正则匹配,union和select没有被空格直接连接,可能逃脱检测。
  • 内联注释:MySQL特有的/*!...*/注释,其中的内容会被MySQL执行,但其他数据库或解析器可能忽略。这可以用来包裹整个恶意语句,或者指定数据库版本。
    /*!50000UNION*/ /*!50000SELECT*/ 1,2,3 --
    这表示在MySQL 5.00.00及以上版本执行内部的语句。

实操心得:注释符的选择很重要。--(后面有个空格)在URL中需要编码为--+或--%20。#在URL中表示锚点,需要编码为%23。/**/最通用,但要注意不要破坏SQL语法。

3.2 空白符的多样化

WAF规则里的[[:space:]]+通常只匹配常规空格、制表符、换行符。我们可以使用非常规空白符:

  • 水平制表符:%09(URL编码)
  • 换行符:%0a,%0d,%0d%0a
  • 垂直制表符:%0b
  • 换页符:%0c

例如:

union%0aselect 1,2,3 unio%0bn%0cselect 1,2,3

这些字符在SQL中通常也被视为空白,能正常分割关键字,但可能绕过简单的空白匹配规则。

3.3 大小写与双写绕过

  • 大小写混合:针对不区分大小写的匹配规则(/union select/i),这招无效。但有些老旧或配置不当的WAF可能使用区分大小写的匹配,这时UnIoN SeLeCt可能有效。
  • 双写关键字:这是一种针对简单字符串替换型过滤的绕过。如果防护代码是$input = str_replace(‘union’, ‘’, $input),那么ununionion经过替换后,中间的union被移除,两边的字符又组成了一个新的union。
    ununionion selselectect 1,2,3 --

4. 编码与混淆:让Payload“面目全非”

当字符级绕过无效时,我们需要对Payload进行更深层次的“化妆”。

4.1 URL编码与多重编码

  • 全编码:将整个或部分Payload进行URL编码。
    union select -> %75%6e%69%6f%6e%20%73%65%6c%65%63%74
    如果WAF没有解码或只解码一次,就可能绕过。
  • 部分编码:只编码关键字符。例如,编码空格为%20,单引号为%27,等号为%3d。
    %27%20and%201%3d1%20--%20
  • 多重编码:对已经编码的字符串再次编码。%本身编码为%25。
    select -> %73%65%6c%65%63%74 -> %25%37%33%25%36%35%25%36%63%25%36%35%25%36%33%25%37%34
    这主要用于对抗一些简单的解码逻辑。

4.2 十六进制与Unicode编码

  • 十六进制编码:在MySQL中,字符串可以用0x开头表示。
    union select 1,2,0x70617373776f7264 from users -- (0x70617373776f7264 是 ‘password’ 的十六进制)
    这可以绕过对特定敏感单词(如password)的检测。
  • Unicode编码:利用数据库对特定Unicode字符的兼容性。例如,在某些环境下,%u0055代表 ‘U’。但这种方式通用性不强,严重依赖于数据库和连接驱动的配置。

4.3 等价函数与语法替换

如果某个函数(如sleep())被禁,我们可以寻找功能相同的替代品。

  • 延时函数替换:
    • sleep(5)->benchmark(10000000, md5(‘test’))(执行大量运算达到延时效果)
    • PostgreSQL:pg_sleep(5)->generate_series(1,10000000)
  • 字符串连接函数:
    • MySQL:concat()->concat_ws(),group_concat()
    • ‘a’+’b’(在某些数据库如MSSQL中可用)
  • 信息获取函数:
    • 获取当前用户:user()->current_user(),system_user(),session_user()
    • 获取数据库:database()->schema()

4.4 特殊符号与语法技巧

  • 反引号、引号:在MySQL中,反引号`用于包裹数据库名、表名、字段名。有时可以用于分隔关键字。
    union`select 1,2,3 -- (可能语法错误,但有时能干扰解析)
  • 科学计数法:数字1可以写成1e0,0.1可以写成.1。在数字型注入中,可以用于绕过对纯数字的简单过滤。
    id=1 and 1e0=1e0
  • 括号与表达式:大量使用无意义的括号或数学表达式。
    id=1 and (1)=(1) id=1 and (select(1))=(1) id=1 and (select+1)!=2

5. 高级绕过技术:利用解析器差异与逻辑缺陷

当常规混淆无效时,我们需要更深入地研究WAF与数据库的解析差异。

5.1 HTTP参数污染

HTTP参数污染(HPP)是指向同一个参数名提交多个值。例如:?id=1&id=2。不同的Web服务器和WAF处理方式不同:

  • Apache/PHP:通常取最后一个值(id=2)。
  • IIS/ASP.NET:通常取所有值,用逗号连接(id=1,2)。
  • J2EE/Tomcat:通常取第一个值(id=1)。

绕过思路:如果WAF只检查第一个id参数,而应用程序(如PHP+Apache)使用最后一个id参数,我们就可以构造:

?id=1&id=2 union select 1,2,3 --

WAF看到id=1(安全),放行。应用程序使用id=2 union select 1,2,3 --,成功注入。

5.2 分块传输编码

分块传输编码是HTTP/1.1的一种特性,允许将请求体分块发送。有些WAF可能无法正确解析分块格式,或者解析逻辑与后端服务器不同。通过工具(如Burp Suite的 “Chunked-encoding converter” 扩展)可以将Payload编码为分块格式,可能绕过一些WAF的请求体检测。但这需要对HTTP协议有较深理解,且成功率因WAF而异。

5.3 畸形请求与协议级绕过

这属于更高级的技巧,包括:

  • 请求方法混淆:将POST请求改为GET,或者使用非标准的HTTP方法。
  • Content-Type混淆:例如,将application/x-www-form-urlencoded改为multipart/form-data或text/plain,WAF的解析器可能无法正确处理。
  • 参数位置变换:将注入参数从URL查询字符串移到Cookie、HTTP头(如X-Forwarded-For、User-Agent)或JSON/XML请求体中。WAF可能默认只检测URL和POST body,忽略其他部分。

5.4 利用数据库特性与注释陷阱

  • MySQL/*!*/注释的版本控制:/*!50000select*/只有在MySQL版本>=5.00.00时才会被执行。可以用于构造在特定环境下才触发的Payload。
  • 嵌套注释与解析错误:过于复杂的注释嵌套可能导致解析器崩溃或行为异常。例如:/*!/*!select*/ */。但这需要大量测试。
  • 利用数据库对字符集的宽松解析:某些数据库在特定字符集下,可能会将一些特殊字符视为空白或忽略。

6. 自动化工具辅助与手工结合

虽然手工构造Payload能锻炼思维,但在实战中,我们常借助自动化工具提高效率。最著名的就是sqlmap。sqlmap内置了大量绕过脚本(tamper),它们就是上述各种技巧的自动化实现。

6.1 常用sqlmap tamper脚本解析

使用sqlmap -u “url” –tamper=”脚本名”来调用。了解脚本原理比单纯使用更重要:

  • space2comment:用/**/替换空格。对应我们手工的注释拆分。
  • space2plus/space2randomblank:用+或随机空白符替换空格。
  • between:用not between 0 and #替换>。用不等价但逻辑相同的语法。
  • charencode/chardoubleencode:URL编码/双重URL编码。
  • randomcase:随机大小写。
  • equaltolike:用like替换=。
  • greatest:用greatest()函数绕过>比较。
  • apostrophemask:用%EF%BC%87(全角单引号)替换单引号’。
  • versionedmorekeywords:在关键字前添加MySQL版本注释,如/*!50000UNION*/。

实操流程:

  1. 先进行基本探测:sqlmap -u “http://target.com/page?id=1” –batch
  2. 如果被WAF拦截,尝试使用通用组合:–tamper=”space2comment,randomcase”
  3. 根据拦截特征(如拦截了union但没拦截select),选择针对性脚本。可以查看sqlmap的tamper/目录下的脚本源码学习。
  4. 使用–random-agent随机化User-Agent,使用–delay设置请求延迟,避免触发频率限制。

注意事项:不要过度依赖自动化。sqlmap的流量特征非常明显,高强度的WAF很容易识别并封禁IP。应该先用手工方式探测出WAF的薄弱点(例如,发现它不检测Cookie中的参数),再指导sqlmap针对性地进行测试(例如,用–cookie=”id=1*”指定注入点)。

7. 实战场景与综合Payload构造

理论需要结合实践。我们模拟一个常见场景:一个搜索功能,参数为keyword,疑似存在字符型注入,但部署了云WAF。

初始测试:

keyword=test’ and ‘1’=’1

返回正常。

keyword=test’ and ‘1’=’2

返回异常。确认存在注入。但当我们尝试:

keyword=test’ union select 1,2,3 –

立刻被WAF拦截。

逐步绕过尝试:

  1. 尝试注释拆分和空白符:

    keyword=test’%0aun/**/ion%0dsel/**/ect%201,2,3%23

    (%0a换行,/**/拆分,%0d回车,%23是#) 如果依然被拦,进入下一步。

  2. 尝试等价函数和编码: 假设我们需要获取数据库版本。直接version()可能被拦。

    keyword=test’%0aun/**/ion%0dsel/**/ect%201,@@version,3%23

    (使用@@version全局变量替代version()函数) 或者对关键字进行十六进制编码的一部分(需要数据库支持):

    keyword=test’ and (select mid(@@version,1,1))=0x35%23

    (判断版本第一位是否是 ‘5’,0x35是 ‘5’ 的十六进制)

  3. 尝试参数污染: 如果应用是PHP,可能取最后一个参数。

    keyword=test’&keyword=a’ union select 1,2,3%23

    将恶意Payload放在第二个keyword参数。

  4. 改变参数位置: 查看请求,发现还有一个X-Forwarded-For头。尝试将注入点移到头部(需要应用代码存在漏洞):

    GET /search?keyword=test HTTP/1.1 Host: target.com X-Forwarded-For: 127.0.0.1’ union select 1,2,3%23
  5. 综合构造最终Payload: 经过测试,发现WAF对union select检测严格,但对||(Oracle/PostgreSQL连接符)或+(MSSQL连接符)检测不严,且应用是MySQL,但支持||作为逻辑或?不,MySQL默认||是逻辑或,除非更改模式。我们换一种思路,使用报错注入,因为报错注入的Payload往往更“畸形”。

    keyword=test’ and updatexml(1,concat(0x7e,(select%0auser()),0x7e),1)%23

    将select user()用%0a换行分隔。如果updatexml被拦,可以尝试extractvalue:

    keyword=test’ and extractvalue(1,concat(0x7e,(select%0a@@version)))%23

常见问题与排查技巧实录:

  • 问题1:无论怎么构造,都返回相同的WAF拦截页面。

    • 排查:可能IP已被WAF拉黑。更换IP或使用代理池。也可能是触发了频率限制,需要大幅降低请求速度,加入随机延迟。
  • 问题2:Payload在本地测试成功,但打到目标上无效。

    • 排查:首先确认注入点类型(字符/数字/搜索型)是否正确。字符型需要闭合引号。其次,检查数据库类型。MySQL的Payload不一定适用于MSSQL。使用@@version、version()、db_name()等数据库特有的函数进行探测。
  • 问题3:联合查询能执行,但无法获取数据,显示的列数不对。

    • 排查:联合查询要求前后列数、数据类型一致。先用order by N确定列数。然后观察页面回显点。将想要的数据放到回显的位置上。例如union select 1,2,3,如果页面在显示“2”和“3”的位置输出了我们查询的结果,那么后续查询就应该是union select 1, database(), user()。
  • 问题4:使用sqlmap的tamper脚本依然被拦截。

    • 排查:WAF可能已经识别了sqlmap的tamper特征。尝试组合使用不常见的tamper脚本,或者自己编写tamper脚本。更有效的方法是,先手工fuzz出一个能绕过的简单Payload(比如一个能触发的布尔盲注条件),然后用这个Payload作为模板,通过sqlmap的–prefix和–suffix参数来指导其测试,而不是完全依赖自动化的tamper。
  • 问题5:目标是JSON或XML格式的API接口。

    • 排查:注入点可能在JSON的某个值里。例如{“id”: “1’ and ‘1’=’1”}。需要将整个JSON作为POST数据发送,并设置Content-Type: application/json。WAF可能对JSON的解析不完善。同样,可以尝试JSON语法混淆,比如插入多余的逗号、换行符等。

绕过WAF是一个持续对抗的过程。今天有效的技巧,明天可能就被加入规则库。因此,最核心的能力不是记住所有Payload,而是掌握分析WAF行为、理解HTTP/SQL解析差异、并灵活组合各种混淆技巧的思维。在实战中,保持耐心,从最简单的测试开始,观察每一次请求的响应变化,逐步迭代你的Payload,这才是通往成功的路径。最后,请务必在合法授权的范围内进行所有测试,技术本身无罪,但使用技术的意图和方式决定了它的性质。

相关新闻

  • 2026年第五届算法、数据挖掘和信息技术国际会议(ADMIT 2026)
  • ios云手机稳控环境不卡顿 苹果云手机原生真机更安全
  • 巴西开闸,iOS 支付规则进入碎片化时代

最新新闻

  • 低成本 高精度:MEMS 惯卫组合导航赋能测绘侦察载荷
  • DeepAgents 之interrupt_on人工审批
  • Ventoy终极指南:一键创建万能启动U盘,彻底告别重复格式化烦恼
  • 【毕业设计】 基于移动端小程序的物联网菇房环境智能管理系统设计与实现 SpringBoot框架支撑的物联网菇房监测管控系统小程序(源码+文档+远程调试,全bao定制等)
  • IntelliJ IDEA在Ubuntu上安装失败的7大坑:92%新手踩过的依赖冲突、Java版本错配与snap权限陷阱(附自动修复脚本)
  • 戴尔G15散热控制终极指南:如何用开源工具彻底告别AWCC卡顿烦恼

日新闻

  • Qwen2.5-Turbo百万上下文实战指南:百炼平台长文本处理全解析
  • 怎么监控对标账号更新,2026年作者监控工作流,5款深度对比
  • EdgeRemover:专业级Windows Edge浏览器管理工具,彻底解决顽固软件卸载难题

周新闻

  • Visual C++运行库修复终极指南:5分钟快速解决Windows软件启动错误
  • 手把手教你构建统计局地区经济数据爬虫:从环境搭建到数据持久化全指南
  • 2026多Agent深度解析:用AI团队替代单一模型,四种架构实战落地

月新闻

  • 【总结】入门篇:50句话让你记住架构核心概念
  • WeChatMsg技术方案解析:实现Mac微信数据自主管理的完整解决方案
  • WeChatMsg:革新性微信数据备份方案,打造你的专属数字记忆库

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号