
1. 项目概述一次针对WAF的“参数污染”实战演练最近在和小伙伴们复盘一些经典的Web安全案例时Less29这个靶场关卡被反复提及。它的标题“参数污染绕过WAF”听起来就很有挑战性直接点出了两个核心SQL注入和绕过Web应用防火墙。这可不是一个简单的注入点测试而是一场针对防护机制的“攻防演练”。很多刚入门安全测试的朋友学会了基础的‘ or 11 --一遇到WAF就束手无策觉得注入点被封死了。Less29恰恰提供了一个绝佳的思维训练场它模拟了一个被简单WAF保护的登录场景但通过一种名为“HTTP参数污染”的技巧我们依然可以找到突破口完成注入。这就像一把锁你以为钥匙孔被堵住了实际上只是需要换个角度和手法去开锁。这个项目适合所有对Web安全、渗透测试感兴趣的朋友无论是正在学习安全知识的学生还是希望提升实战能力的运维、开发人员。通过复现Less29你不仅能巩固SQL注入的原理更能深入理解WAF的工作机制与局限性掌握一种在特定场景下非常有效的绕过思路。我会带你从环境搭建开始一步步分析WAF的拦截逻辑然后手把手演示如何利用参数污染“骗过”WAF最终执行我们想要的SQL语句。过程中会穿插大量原理讲解和踩坑记录确保你能看懂、能复现、更能理解背后的“为什么”。2. 核心原理与WAF拦截逻辑拆解2.1 SQL注入与WAF的基本攻防在深入Less29之前我们必须把战场情况搞清楚。SQL注入的本质是攻击者通过Web应用程序的输入点插入恶意的SQL代码从而欺骗后端数据库执行非预期的操作。比如一个登录框正常的SQL语句可能是SELECT * FROM users WHERE username ‘admin‘ AND password ‘123456‘如果用户名输入admin‘ --语句就变成了SELECT * FROM users WHERE username ‘admin‘ -- ‘ AND password ‘123456‘--后面的内容被注释掉密码验证形同虚设。而WAFWeb应用防火墙就是矗立在Web应用前面的“哨兵”。它通常以软件或硬件的形式存在通过分析HTTP/HTTPS流量根据预设的规则集如正则表达式匹配union select、sleep(、benchmark(等关键字或检测单引号、等号的数量异常来识别和阻断攻击请求。一个简单的WAF规则可能像这样如果检测到请求参数中包含‘单引号和or、and等SQL关键字组合出现就直接返回拦截页面。2.2 Less29靶场环境与WAF行为分析Less29靶场通常指Web安全学习平台如DVWA、SQLi-Labs中的一关模拟了一个典型的登录场景后端代码大概逻辑是获取用户输入的用户名和密码拼接成SQL查询语句。同时它前面部署了一个“简单”的WAF。这个“简单”是关键它意味着WAF的检测逻辑可能存在缺陷而不是无懈可击。我们首先进行常规探测。假设登录接口是/Less-29/login.php参数为id。我们尝试经典注入载荷GET /Less-29/login.php?id1‘此时浏览器很可能返回一个WAF拦截页面提示“非法输入”或“攻击被阻断”。这说明WAF确实在工作它检测到了单引号这个危险字符。注意这里的WAF是靶场模拟的其规则相对固定和已知。真实环境的WAF如Cloudflare、ModSecurity等规则集要复杂得多但绕过思路有相通之处。接下来我们尝试不带单引号的探测GET /Less-29/login.php?id1 and 11同样被拦截。因为WAF规则很可能也匹配了and、or这类SQL关键字。甚至11这种布尔表达式也可能触发基于关键字的规则。那么WAF是如何获取参数值的呢这里就引出了HTTP参数解析的一个关键点。当请求/Less-29/login.php?id1id2时不同的技术栈对重复参数名的处理方式不同PHP/Apache通常取最后一个值即id2。J2EE/Tomcat通常取第一个值即id1。Python Flask会得到一个包含所有值的列表[‘1‘, ‘2‘]。ASP.NET/IIS行为也可能不同。Less29靶场设计的精妙之处就在于它假设WAF和后端应用对重复参数的处理方式不一致。这是参数污染攻击能够成立的核心前提。2.3 HTTP参数污染攻击原理详解HTTP参数污染简称HPP是一种利用HTTP请求中同名参数解析差异进行攻击的技术。在绕过WAF的场景下其攻击模型如下攻击者构造请求发送一个包含多个同名参数的HTTP请求例如?id合法值id注入载荷。WAF解析WAF按照自己的解析逻辑比如取第一个参数值对请求进行检查。它检查id合法值发现是干净的于是放行。后端应用解析后端应用如PHP按照自己的解析逻辑比如取最后一个参数值处理请求。它拿到的是id注入载荷。结果恶意注入载荷成功绕过WAF的检测直达后端数据库执行。这就造成了“一个请求两种解读”的局面。WAF看到的是无害的“羊皮”而后端应用拿到的是危险的“狼牙”。Less29正是基于这个原理设计的。我们需要做的就是找出WAF和后端分别如何处理重复的id参数。3. 实战探测与绕过步骤拆解3.1 环境准备与初步信息收集首先你需要搭建或访问一个包含Less29的靶场环境例如SQLi-Labs。确保你能正常访问到登录页面。打开浏览器开发者工具F12切换到“网络”标签页这样我们能清晰地看到所有请求和响应。第一步确定注入点类型。通常Less29是一个基于GET请求的注入参数名是id。所以我们构造的URL形如http://target/Less-29/index.php?id1。第二步判断是否存在注入。先输入正常值id1页面显示正常信息比如登录成功或用户信息。然后输入id1‘观察是否被WAF拦截。如果被拦截证实了WAF的存在。再尝试id1 and 11同样可能被拦截。3.2 探测参数解析顺序差异这是最关键的一步。我们需要探明WAF和后端各自“偏爱”第几个参数。方法一利用报错信息构造请求GET /Less-29/index.php?id1‘id2如果返回数据库报错如“You have an error in your SQL syntax”说明后端应用PHP取的是第一个id1‘并因其包含单引号导致SQL语法错误。而WAF可能取的是第二个id2认为请求安全所以放行了。这证明WAF取最后一个值。如果页面显示正常如显示id2对应的内容说明后端应用取的是第二个id2WAF取的是第一个id1‘并进行了拦截。但由于WAF拦截了我们看不到响应不这里需要仔细看如果WAF拦截通常会返回一个明确的阻断页面如403、警告页。如果返回的是正常应用页面说明WAF放行了。那么WAF检查id1‘时为什么放行这可能意味着WAF的规则有漏洞或者它取了别的值。更可能的情况是WAF取了第一个值id1‘但它的规则没检测出来我们换一下。让我们系统性地测试请求A:?id1id2‘观察如果页面显示id1的内容且无报错说明后端取第一个值(1)WAF可能也检查第一个值(1)所以安全。如果页面报错说明后端取第二个值(2‘)WAF检查的可能是第一个值(1)所以放行了。这符合我们的绕过模型。请求B:?id1‘id2观察如果页面报错说明后端取第一个值(1‘)WAF检查的可能是第二个值(2)所以放行。这也符合绕过模型。如果页面显示id2的内容说明后端取第二个值(2)WAF检查第一个值(1‘)并可能拦截。在经典的Less29设定中通常的结论是WAF解析时取第一个id参数的值进行检查而后端PHP程序取最后一个id参数的值进行数据库查询。因此我们的攻击载荷应该放在第二个id参数的位置。3.3 构造绕过Payload实施注入确定了顺序假设WAF取第一个后端取最后一个我们就可以开始构造真正的注入语句了。步骤1验证注入点绕过WAF原本id1‘ and ‘1‘‘1会被WAF拦截。现在我们利用参数污染GET /Less-29/index.php?id1id1‘ and ‘1‘‘1WAF看到的是id1干净放行。后端PHP执行的是id1‘ and ‘1‘‘1。 如果页面返回与id1正常时相同的内容说明注入成功且是字符型注入。步骤2判断字段数order by使用order by探测同样需要将恶意部分放在第二个参数。?id1id1‘ order by 3 --不断尝试order by 4,order by 5...直到页面返回错误即可确定字段数。假设字段数为3。步骤3联合查询获取数据union select这是获取数据库信息的关键。Payload构造如下?id1id-1‘ union select 1,2,3 --这里id-1是为了让前一个查询不返回结果从而页面显示我们union select的结果。通过观察页面哪个位置显示了2或3来确定数据回显点。假设2和3的位置可以回显数据接下来?id1id-1‘ union select 1, database(), version() --这样我们就在绕过WAF的情况下成功获取了当前数据库名和数据库版本信息。步骤4进一步获取表名、列名和数据这个过程就是标准的联合查询注入流程只是每个Payload都需要套上参数污染的“外壳”。获取表名?id1id-1‘ union select 1,group_concat(table_name),3 from information_schema.tables where table_schemadatabase() -- 获取某表如users的列名?id1id-1‘ union select 1,group_concat(column_name),3 from information_schema.columns where table_name‘users‘ -- 获取数据?id1id-1‘ union select 1,group_concat(username,0x3a,password),3 from users --实操心得在构造Payload时空格有时也会被WAF拦截。可以尝试用/**/MySQL注释符代替空格或者用、%20、%09Tab等编码形式。例如union/**/select。在参数污染的场景下这些绕过技巧可以叠加使用。4. 深度技术细节与变种绕过探讨4.1 WAF规则的可能弱点与更多绕过思路Less29展示的只是参数污染的一种典型应用。实际中WAF的规则和解析逻辑可能更复杂但思路是相通的。除了“首尾取值差异”还有其他一些可能的弱点参数解析层级差异WAF可能只解析查询字符串?后面的部分但对通过POST Body、JSON或XML传递的参数解析不深。如果应用同时接受GET和POST的同名参数且处理优先级不同也可能产生污染。大小写、编码与混淆WAF的规则可能是大小写敏感的Union可能绕过union的检测。或者对URL编码、双重URL编码、特殊字符如换行符%0a的处理与后端不一致。例如将union select编码为u%6eion s%65lectWAF可能解碼后检测而后端可能直接拼接字符串导致检测失效。注释符干扰在参数中插入SQL注释符可能破坏WAF的正则表达式匹配。例如id1‘/*!and*/‘1‘‘1。MySQL特有的/*! ... */内联注释里面的代码在其他数据库会被当作注释但在MySQL中会执行这可以用来绕过一些简单的关键字过滤。4.2 自动化工具中的参数污染利用在实战渗透测试中我们通常会使用sqlmap这样的自动化工具。sqlmap也内置了参数污染绕过技术。使用--tamper参数可以调用脚本对Payload进行混淆其中与参数污染相关的技巧可以通过--hppHTTP Parameter Pollution选项来启用。例如对一个疑似存在HPP绕过点的目标可以这样使用sqlmapsqlmap -u “http://target/Less-29/index.php?id1“ --hpp --batch--hpp选项会让sqlmap尝试使用参数污染技术来测试和利用注入点。它会自动探测最佳的污染位置是放在前面还是后面并构造相应的Payload。注意事项自动化工具虽然强大但噪音也大容易触发WAF的频次拦截或更高级的行为分析。在授权测试中建议先用手工方式确认漏洞存在和绕过原理再使用工具进行深度利用和数据提取这样理解更深刻也更具针对性。4.3 防御视角如何防范参数污染攻击作为开发或安全人员了解攻击是为了更好的防御。要防范此类攻击需要多层面入手应用程序层使用预编译语句Prepared Statements这是根治SQL注入的终极方案。使用参数化查询让数据库将代码和数据严格区分无论参数如何污染注入的代码都不会被执行。严格的输入验证不仅验证类型、长度、格式对于同名的参数在代码中明确处理逻辑例如只取第一个或最后一个并记录日志对于传递多个同名参数的非正常请求可以予以警告或拒绝。规范化输入在处理前对参数进行标准化例如解码URL编码、去除多余空格、统一字符集等避免利用编码差异的绕过。WAF部署层协调解析逻辑确保WAF与后端应用服务器Apache、Nginx、IIS等对HTTP请求的解析逻辑保持一致。这需要WAF厂商和应用开发团队进行沟通。增强检测能力WAF规则应能检测HPP攻击模式例如检查同一个参数名是否在请求中多次出现并将其组合起来进行威胁评估而不是孤立地检查某一个值。启用学习模式在安全上线初期让WAF在观察模式下运行学习正常的业务参数传递模式从而能更好地识别异常的多参数请求。5. 常见问题排查与实战心得记录5.1 问题排查清单在复现Less29或类似场景时你可能会遇到以下问题问题现象可能原因排查步骤与解决方案使用参数污染后页面依然被WAF拦截。1. WAF与后端解析顺序判断错误。2. WAF规则较智能能关联检测多个参数。3. Payload本身触发了其他规则如关键字。1. 重新用id1‘id2和id1id2‘测试确认报错情况准确判断顺序。2. 尝试在“干净”的参数值中也加入少量干扰如id1/*id2*/ OR 11。3. 对Payload进行混淆如用/**/代替空格对关键字进行大小写变换或编码。页面返回正常但union select没有回显数据。1. 字段数判断错误。2. 注入点类型判断错误非字符型可能是数字型。3.union前后查询的字段类型不匹配。1. 重新用order by精确判断字段数。2. 尝试数字型注入Payload?id1id1 and 11。3. 在union select后尝试用null代替数字如union select null, null, null。自动化工具sqlmap使用--hpp选项无法检测到注入。1. 目标点不存在注入漏洞。2. sqlmap的污染策略与目标环境不匹配。3. 有其他更强的防护如Token、动态参数。1. 首先用手工方式确认漏洞是否存在。2. 尝试调整sqlmap的--level和--risk参数提高检测强度。3. 查看sqlmap的详细日志(-v 3)观察其发送的Payload和响应进行手动分析调整。后端没有报错信息也无法进行联合查询。可能是盲注Boolean Blind或Time Blind。1. 尝试布尔盲注Payload?id1id1‘ and length(database())1 --通过页面内容差异判断。2. 尝试时间盲注Payload?id1id1‘ and sleep(5) --观察页面响应是否延迟。5.2 个人实操心得与进阶思考心态很重要遇到WAF不要慌它只是一个规则集合总有逻辑边界。Less29教会我们的不是某个具体的Payload而是一种“差异利用”的思维。多思考“这里WAF会怎么解析”“后端又会怎么解析”“它们为什么不一样”手工优先尤其是在学习阶段坚持手工测试能让你对每一个细节有肌肉记忆。自动化工具是放大器但你的大脑才是核心引擎。搞清楚原理后再用工具提升效率。环境多样性Less29是一种特定场景。真实世界可能遇到JSP、ASP.NET、Python Flask等后端它们的参数解析特性各不相同。平时可以自己搭建多样化的靶场环境进行练习比如研究在Tomcat下如何利用“取第一个参数”的特性进行污染攻击。防御的全面性从防御角度看参数污染攻击提醒我们安全是一个链条。不能只依赖WAF。最根本的还是在应用代码层使用预编译语句和严格的输入处理规范。WAF应作为一道动态的、深度的检测防线而不是唯一的防线。最后技术总是在攻防对抗中演进。今天有效的绕过技巧明天可能就被加入规则库。但通过像Less29这样的深度剖析我们积累的不是一个“死”的Payload而是一种动态的、探究系统行为差异的安全分析能力。这种能力无论是在渗透测试、代码审计还是安全开发中都是无比珍贵的。