拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

目录遍历绕过WAF实战:核心原理与800+Payload测试思路

目录遍历绕过WAF实战:核心原理与800+Payload测试思路 目录遍历这词儿网上随便一搜都是老生常谈可真到实战里能一次绕过去的没几个。我这两年和各类WAF打交道测过Nginx、OpenResty、云WAF、自研网关也带过不少新人做CTF和授权渗透慢慢攒了一套800Payload的测试思路。很多人以为绕WAF就是把编码轮着试一遍其实大错特错。真正的关键是你得搞清楚WAF到底看了什么、没看什么、以及服务端最终拿到了什么。这篇文章我会把目录遍历绕过的核心原理、Payload分类思路、完整实测过程和踩坑记录全部分享出来尤其针对2026年常见的语义分析型WAF给出可落地的测试套路。无论你是CTF选手、渗透测试工程师还是负责WAF运维的防守方这篇都能给你省下大量踩坑时间。1. 目录遍历与WAF拦截的本质你到底在绕什么要说绕过先得明白WAF凭什么能拦住你。目录遍历的基础原理就一句话程序在处理文件路径时没有过滤用户传入的../或..\导致可以跳出原本允许的目录。而WAF拦截的基础原理则是另一句话它会把你这份HTTP请求从头到尾看一遍用正则、规则引擎或机器学习模型找出危险特征。1.1 目录遍历漏洞的产生原因这个漏洞在PHP、Java、Node.js、Python的老代码里很常见尤其是那些直接拼接路径的写法。比如PHP里include($_GET[page])、file_get_contents($_GET[path])或者Java里new File(request.getParameter(file))这类代码默认认为传入参数就是个普通文件名根本没想过../../etc/passwd这种事。Windows环境还会多一个反斜杠..\的问题很多Linux写法的过滤规则在Windows服务端直接失效。注意目录遍历不光是读文件配合文件包含还能执行代码配合上传功能还能做到写文件。但底层逻辑一致只要路径可控就存在逃逸风险。这也解释了为什么CTF里目录遍历题基本都是送分题——因为它原理简单、判别容易可现实中依然大量存在尤其是老旧系统和外包项目。1.2 WAF的检测思路与常见拦截点大多数WAF拦截目录遍历依赖的是正则特征。它们会重点看三个地方URL路径部分比如/download?id../../etc/passwd重点检查参数值。请求头部分程序会把文件名放在X-Filename或Referer头里WAF同样会检查。请求体POST表单或JSON体中的路径字段。检测特征主要是../、..\、%2e%2e、URL编码变体等。看起来很容易对吧但千万不要小看这个过程因为WAF在检查前通常会对原始请求做一层或多层解码、标准化。有的WAF先做一次URL解码再匹配规则有的会先解析Content-Type再做application/x-www-form-urlencoded解码还有的会把/./、//之类的路径标准化。你发的Payload如果跟规则样本差一丁点WAF就可能从“拦截”变成“放行”这正是绕过的空间。1.3 为什么单纯的Payload堆砌没用我在很多技术群看到有人分享所谓“最新绕过Payload合集”但实际上手一测经常全军覆没。原因很简单绕过依赖三个变量的组合——客户端发送形式、WAF解析过程、服务端最终解析结果。你发的..%252fWAF如果只解码一次看到%252f不觉得危险但服务端如果解码两次最终就变成../绕过成功。然而如果你的目标服务端只解码一次呢这个Payload就永远无法触发漏洞只会正常访问不存在的文件。所以我一直主张背Payload不如背“绕过维度”。只要掌握了编码组合、路径语义、平台差异这几个维度你完全可以在测试现场现推Payload甚至比背下来的更精准。2. 800Payload的整理维度与核心分类有人一听800就以为是一张超长列表实际上我整理的这套Payload按构造逻辑分成四大类一通百通。2.1 编码混淆类从单层到多层、从URL到Unicode这是最基础也最常用的一类。核心思路是让WAF正则匹配不到危险字符串但服务端解码后还原为路径穿越。常见编码形式包括Payload示例说明../../etc/passwd原始Payload用于确认漏洞存在..%2f..%2fetc%2fpasswdURL编码斜杠%2e%2e%2f%2e%2e%2fetc%2fpasswd对点和斜杠都编码..%252f..%252fetc%252fpasswd双重URL编码需服务端解码两次%c0%ae%c0%ae%c0%af过宽UTF-8编码老版本Tomcat解析为../..%u2216..%u2216etc%u2216passwdUnicode反向斜杠部分IIS场景..%255c..%255cwindows%255cwin.iniWindows下的双重编码反斜杠%252e%252e%252f双重编码点、斜杠这里最关键的点是编码层数并非越多越好。三层以上编码大概率会让服务端直接当作普通字符串处理不但不解析还可能引发413或400。我实测中单层URL编码和双重URL编码的成功率最高Unicode畸形编码仅对特定中间件有效。测试时建议先用原始Payload确认漏洞再逐层编码试探WAF。2.2 路径语义类利用解析器差异这一类是高级选手最爱用的方式因为不依赖编码逻辑上更干净。核心是让Web服务器或者应用框架在路径标准化时帮你把Payload变成正常路径。常见形式有/download/../../etc/passwd利用多段路径让Web服务器先按路径路由再交给后端。/static/../..//etc/passwd路径中存在多个斜杠。/....//....//etc/passwd某些中间件会把....//标准化为../。..;/..;/etc/passwdTomcat对分号路径参数的解析特性。%2e%2e%2f%2e%2e%2f有时候点和斜杠不统一比如点用URL编码斜杠用原始字符。这类Payload最大的价值在于它能让WAF看到的是“合法路径”而服务端解析时得到的是穿越路径。现代WAF普遍做了URL解码但对路径归一化如/./、//处理并不彻底这给语义类绕过留了空间。2.3 大小写与系统差异类很多人低估了大小写的作用。Windows文件系统不区分大小写但WAF规则是区分大小写的。于是..\..\Windows\System32\drivers\etc\hosts改为..\..\windows\system32\drivers\etc\hosts规则可能就不匹配了。Linux上不存在这个优势因为路径大小写敏感。还有一类是利用Windows设备名比如..\..\con\con这类奇葩路径但这属于另类思路不是主线。大小写绕过只能针对大小写敏感的正则规则如果WAF检测时自动转小写那这条路就走不通。我测试过某云WAF会把整个请求体转小写再匹配所以大小写变体对它是无效的。这里要自己总结目标WAF的行为特征。2.4 干扰字符与混合绕过在Payload里插入无害字符让正则引擎错位也是常见思路。常见的干扰方式有./../../etc/passwd前面加一个./。..%2f./../etc/passwd混合编码与原始斜杠。%2e%2e%2f%2e%2e%2f%2e%2e%2fetc/passwd部分编码部分不编码。使用Tab、换行、空字符如..%09..%09/etc/passwd部分解析器会忽略Tab或将其视为分隔符。在路径参数后加分号如..;/etc/passwd;Tomcat等容器会把分号后内容当参数去掉。JSON参数中插入Unicode转义如{file:..\\u002f..\\u002fetc\\u002fpasswd}如果后端有JSON解析可能还原。干扰字符的原理和编码不同它并不依赖服务端解码而是利用解析器在特定位置的宽容特性。测试时如果能提前知道目标中间件如Tomcat、IIS、NginxPHP-FPM可以直接针对其特性构造。3. 实操从搭建环境到完整绕过流程理论讲再多不如一次实测。下面我会用我的标准流程带你从零验证一套Payload。这套流程我用了三年基本通用。3.1 本地搭建测试环境推荐用Docker快速搭一个包含任意文件读取的漏洞环境。比如一个简单的PHP容器代码为?php $file $_GET[file]; echo file_get_contents(/var/www/html/ . $file); ?启动容器后用BurpSuite把代理挂上确认http://127.0.0.1:8080/?fileindex.php可以正常访问。然后测试http://127.0.0.1:8080/?file../../../../etc/passwd如果能读到说明漏洞成立。如果你想测WAF就在前面挂一个OpenResty或者云WAF实例。国内云WAF一般需要域名接入本地环境可以改用ModSecurity模拟。记住没有WAF时先确认漏洞有WAF时才测绕过顺序不能反。3.2 手工验证三步法我每次拿到一个疑似目录遍历的接口不会急着跑爆破字典而是按三步走第一步确认参数位置与反射方式。是路径参数、查询参数还是POST请求体响应是页面内容还是JSON里的某个字段如果反射内容在响应头或状态码上就需要调整观察方式。第二步用基础Payload探测。发送一次原始../一次URL编码%2e%2e%2f一次双编码%252e%252e%252f。观察状态码、响应长度、是否出现“403 Forbidden”或WAF拦截页。这一步用来判断WAF的拦截粒度。如果原始../被拦而编码后不拦截那就有戏。第三步根据响应差异判断解析深度。假设%2e%2e%2f返回200且内容包含root:说明服务端解码一层如果只有%252e%252e%252f返回200则服务端可能解码两层。这个规律一旦摸清你后面完全可以按需构造。3.3 使用工具批量测试800Payload手工测太慢我通常会把Payload字典丢给BurpSuite Intruder或ffuf跑。BurpSuite适合看状态码与响应长度差异ffuf适合快速过滤响应大小。命令行示例ffuf -u http://target:8080/?fileFUZZ -w traversal_payloads.txt -fs 0 -fw 2注意在-fs里过滤掉默认错误页的大小这样能快速找到响应长度异常的结果。如果目标是POST接口可以改用-d fileFUZZ -X POST。批量测试之后把所有结果按响应长度排序重点关注那些长度明显不同的项。这时候你可能会看到原始Payload被WAF拦截但某个双层编码Payload返回200。这个结果就是你要的。我在实战中测过最绝的一次某WAF把/.*..\//这种正则写成只匹配连续两点一斜杠结果../被拦但....//直接通过。服务端Nginx把....//归一化为../于是成功读到文件。这种东西你不实际跑一遍字典纯靠想是想不出来的。3.4 实战案例一次CTFHub题目的绕过全过程拿CTFHub常见的“目录遍历”来说题目环境往往开着WAF模拟规则。我的测试记录大致是开局直接?file../../../../flag返回403并提示拦截。改成?file..%2f..%2f..%2f..%2fflag依然403。加双重编码..%252f..%252f..%252f..%252fflag状态码变200响应里出现flag内容。后来确认服务端是Nginx PHPNginx先解码一层PHP又解码一层而WAF只检查了原始请求内容没有对二次解码后的内容做规则匹配。这个例子能说明在真实环境里绕过不是靠幸运而是靠搞清楚中间件解码链路。把解码链路画出来你大概率能找到WAF遗漏的那一个环节。3.5 平台差异与Payload选择不同操作系统和中间件的解析差异非常大我整理了一张速查表环境关键特性推荐Payload方向Linux Nginx PHP..%2f对Nginx有时不会合并PHP会处理双重URL编码、....//Windows IIS大小写不敏感、支持反斜杠..\..\windows\win.ini、大小写变体Tomcat分号路径参数、/标准化..;/..;/、%2e%2e%2fSpring BootRFC 3986解析、Unicode编码/..%252f..%252f、Unicode变体Go/ginnet/url会标准化..%2f通常会被保留需编码绕过同一个Payload在Linux下有效不代表在Windows下有效反之亦然。如果你面前是个未知目标那么用一个跨平台字典覆盖所有编码形式是最稳妥的做法这也是800Payload存在的意义。4. 常见问题排查与响应码诊断实录测Payload绕WAF劝退新手的往往是各种奇奇怪怪的响应码和拦截页。下面这些坑我都踩过直接给你排雷。4.1 413 Request Entity Too Large 的真相热词里提到的unexpected status 413 payload too large我最初也摸不着头脑。这个状态码通常由代理服务器或WAF返回意思是请求体或整体请求头超过允许大小。听起来跟目录遍历八竿子打不着但实际测试中经常出现。原因一般有三种你使用的字典里存在超长Payload比如某个Unicode编码字符串有几百字符网关默认限制1MB或8KB直接给你413。WAF检测到大量可疑内容后主动拒绝用413来阻断请求。上游Nginx配置了client_max_body_size默认1MB你POST的数据太大。解决办法很简单控制Payload长度。一个目录遍历Payload最多三四十个字符就够表达全部语义超过80个字符的基本不是好Payload。如果遇到413先检查自己是不是把整个字典丢进了一个请求里或者是否用了POST大体积Body。4.2 403 Forbidden / 405 Method Not Allowed / 200 的区分403 说明WAF精准拦截或者服务端做了目录权限控制。先判断是谁返回的看响应头里有没有WAF指纹。405 一般是方法不允许跟绕过无关。200 且响应长度异常可能是绕过成功的信号。200 但响应内容仍是错误页或首页可能只是路由吞掉了参数不算成功。我习惯在字典里混入一个正常文件请求比如?fileindex.php作为基准。如果请求正常文件是200但?file../../etc/passwd是403说明拦截明确如果?file../../etc/passwd是200但返回内容等于?fileindex.php说明后端可能做了白名单过滤把非法值替换成了默认值。4.3 响应时间与长度差异有些高级WAF会模拟正常响应故意返回一个同样的200页面来误导测试。这时候响应长度可能没差异但响应时间会异常。比如某CDN WAF会把拦截请求也转发到源站导致响应时间比正常快或慢。我排查时会同时记录响应长度、响应时间、状态码三个维度交叉判断。如果三个维度都一样就要考虑是不是返回了缓存内容。4.4 绕过成功的判定标准不要一看到200就觉得成功了。真正的目录遍历成功标志是响应中出现了目标文件的内容特征。比如/etc/passwd里的root:x:0:0Windows的win.ini里的[fonts]。如果只是状态码变了响应内容还是你网站的404页那大概率是假阳性。所以在字典中我会专门放几个强特征文件Linux放/etc/passwd和/etc/hostsWindows放/windows/win.ini。跑完字典只看这些文件对应的Payload是否强特征命中。4.5 常见的WAF指纹识别技巧想绕过先得知道对面是谁。看响应头里的Server和X-Powered-By是最直接的比如Server: openresty说明是Nginx LuaX-WAF-Status: forbidden可能是某个开源WAF。有些云WAF不暴露指纹就通过拦截页标题判断比如出现“安全提醒”“人机验证”等字样。另外用同一个Payload分别测http://ip和http://域名如果结果不同说明有透明WAF介入可以做域名对比测试。5. 防守方视角如何让目录遍历和WAF都失效聊完绕过得聊聊守。因为绕过研究得越深越能理解防守方应该怎么加固。这部分是给开发和安全运维的实操建议。5.1 服务端代码层的根本修复目录遍历的修复根本不在WAF而在代码层。最稳妥的方案是使用语言内置的规范化函数PHPrealpath()解析后检查是否在预定目录内。Javanormalize()startsWith()。Pythonos.path.abspath()后比对前缀。Node.jspath.resolve()后检查前缀。以PHP为例$base /var/www/html/; $path realpath($base . $_GET[file]); if ($path false || strpos($path, $base) ! 0) { die(非法路径); }这样无论攻击者如何编码最终落到文件系统的一定是真实路径无法逃逸。另外从文件名中剥离路径也是一个思路只取basename($_GET[file])但要注意Windows下basename对反斜杠处理的坑。5.2 白名单与规范化输入如果业务上只能允许某些文件被访问直接做白名单最安全。比如地图数据、导出报表、附件下载把允许的文件名校验到数组里$allowed [report_2026.pdf, manual.pdf]; if (!in_array($_GET[file], $allowed, true)) { http_response_code(403); exit; }白名单一上再强的绕过Payload都没用。如果文件列表太多可以用前缀目录检查加后缀过滤。反正原则是不要信任何输入只信规范化后的绝对路径。5.3 WAF规则优化核心解码层数与路径标准化从WAF运维角度最常见的不足是只做一层URL解码、不处理二次编码和路径归一化。我的建议是对请求参数做至少两层URL解码后再匹配规则但要注意不要影响业务数据里的合法%。在规则库中加入%252f、%25252f等常见双重编码样本。对路径部分做标准化合并/./、//、/../后再匹配目录穿越特征。将大小写不敏感应用于路径检测特别是Windows场景。增加对分号路径参数、反斜杠、Unicode特殊字符的规则。一句话总结凡是服务端可能复原的形态WAF都要尝试复原一遍。你只有比攻击者多解码一层才能说自己在防守否则就是靠运气。5.4 日志监控与告警特征即使WAF没拦住完善的日志监控可以作为第二道防线。建议在访问日志中对以下特征单独标记并告警参数值中包含../、..\、%2e%2e、%252e%252e等字符。访问了系统敏感文件路径如/etc/passwd、/windows/win.ini、.env。单个URL参数中包含超过2个斜杠编码形态。响应状态码为200但响应长度与同类型正常请求差异超过50%。把这些特征做成实时告警即使被绕过你也能在第一时间发现并止损。很多时候攻击者绕过了WAF但忘记了删除访问日志这恰恰是防守方最该抓住的机会。5.5 从绕过的角度反查漏洞我在做红队时有个习惯每发现一个绕过思路就记下来反手就能给客户提加固建议。比如你发现某WAF不查双重编码那么建议运维在WAF规则里增加双重解码匹配你发现....//能过就建议网关层增加路径标准化模块。攻防本就是互相推动的过程这份800Payload字典与其说是攻击武器不如说是一份防守自查清单更贴切。6. 把Payload整理成自己的字典一点个人心得最后分享一个实用经验特别适合刚入行的人。网上有很多现成的Payload列表但直接拿来用往往效率低。我的做法是按自己的测试环境验证过的结果重新整理字典。每次测通一个新Payload就记录三栏原始Payload、目标环境、WAF行为。久而久之你会积累一份真正属于自己的高命中率字典而不是网上抄来的大杂烩。比如你会慢慢发现某个客户内部系统用老版本Tomcat那么..;/..;/的命中率奇高另一个系统用Nginx反代PHP-FPM那么..%252f才是王道。这种环境关联是纯列表给不了你的。把800Payload按环境打标签之后跑起来不需要盲目爆破直接挑几个高优先生试又快又准。另外无论攻防都要坚守授权边界。所有测试必须在你有合法授权的目标上进行否则再牛的技术也会变成事故。目录遍历这种漏洞虽然经典但从未消失每一轮测试背后的核心不是“背了多少Payload”而是“理解了解析链路的每一环”。搞懂了WAF和服务端的输入输出差异你手里的字典随便减到几十条也一样能打。这份能力才是真正值得长期投资的东西。
返回列表