
1. 项目概述从一次真实的文件泄露事件说起去年我参与了一个企业级内容管理系统的安全审计。在看似固若金汤的登录认证和权限校验背后我们通过一个再普通不过的“文件预览”功能仅仅修改了URL中的一个参数就成功读取到了服务器上存放着数据库连接密码的配置文件。攻击路径简单到令人惊讶而这就是典型的路径遍历漏洞。路径遍历也叫目录遍历是Web安全领域中一种古老但远未绝迹的攻击手法。它利用的是应用程序在处理文件或目录路径时未能对用户输入进行充分净化和校验导致攻击者能够跳出预期的目录限制访问或操作服务器文件系统的任意文件。对于开发、测试和安全运维人员来说理解路径遍历攻击的原理、挖掘方式、利用手法以及防御策略是一项基础且至关重要的技能。这不仅仅是CTF比赛中的常客更是真实渗透测试和红蓝对抗中的“敲门砖”。很多中高级漏洞的利用链往往就是从这样一个简单的路径遍历开始的它可能为你后续的提权、横向移动打开第一扇门。本文将从一个从业者的视角彻底拆解路径遍历攻击不仅告诉你“是什么”和“怎么做”更会深入探讨“为什么”会这样以及在实际生产环境中如何系统性地防御和排查。2. 路径遍历攻击的核心原理与常见场景2.1 漏洞产生的根本原因路径遍历漏洞的根源在于“信任边界”的混淆。Web应用程序的逻辑是用户通过参数如filenamereport.pdf指定一个文件程序将这个参数与一个预设的基础目录如/var/www/uploads/拼接形成最终的文件路径如/var/www/uploads/report.pdf然后进行读取或下载操作。问题就出在拼接环节。如果程序天真地认为用户输入的filename参数永远是一个“干净”的文件名而不对其进行任何检查攻击者就可以注入包含目录遍历序列如../的字符串。例如当攻击者提交filename../../../etc/passwd时程序拼接出的路径可能变成/var/www/uploads/../../../etc/passwd。在操作系统的路径解析规则中../表示上一级目录经过规范化后这个路径就等价于/etc/passwd。于是程序在不知不觉中越过了为它划定的“牢笼”/var/www/uploads/读取了系统敏感文件。这里的关键在于程序没有对用户输入实施“最小权限原则”和“白名单校验”。它过度信任了来自不可信源用户输入的数据。2.2 攻击的常见入口点路径遍历漏洞可能隐藏在任何一个接收文件或目录路径参数的功能点背后。以下是一些高危的常见场景文件下载/查看功能这是最经典的场景。参数名常为file、filename、path、document等。例如/download?fileweekly_report.docx。图片/资源加载网页中通过动态参数加载图片、CSS、JS等静态资源。例如/loadImage?imgavatar.png。文件包含功能某些语言如PHP的include、require函数如果使用了动态变量就可能构成“本地文件包含”其本质是路径遍历的一种特殊形式危害更大因为它能执行代码。压缩包解压允许用户上传压缩包并自动解压到服务器特定目录。如果压缩包内含有恶意构造的包含../的路径而解压程序未做安全处理文件就可能被解压到预期之外的目录。日志查看器系统后台提供的日志查看功能通过参数指定日志文件路径。配置文件备份/恢复一些管理后台允许备份配置文件攻击者可能通过遍历读取其他应用的配置。注意不要只盯着明显的“下载”功能。任何将用户输入的一部分直接或间接用于文件系统操作的地方都可能是潜在的漏洞点。审计时需要有“攻击者思维”思考每个参数是否可能被用来指向一个文件路径。2.3 路径遍历序列的“花式”绕过随着安全意识的提升简单的../过滤已很常见。但道高一尺魔高一丈攻击者发展出了多种绕过技术编码绕过URL编码../可以被编码为%2e%2e%2f、..%2f、%2e%2e/。双重URL编码../-%2e%2e%2f-%252e%252e%252f有些解码函数会执行两次解码。Unicode编码在特定环境下可能被解析。绝对路径绕过如果程序只是简单地在用户输入前添加基础路径那么直接提交绝对路径可能有效。例如参数filename/etc/passwd拼接后变成/var/www/uploads//etc/passwd在某些系统/语言中多个/会被视为一个或者程序逻辑错误地处理了绝对路径。空字节截断在较老的系统或特定语言版本中空字节%00或\0会被视为字符串结束符。如果程序使用黑名单过滤../后再拼接后缀如.txt攻击者可以提交../../../etc/passwd%00过滤后文件名可能变成../../../etc/passwd%00但拼接后缀时%00后的.txt被截断最终访问的是/etc/passwd。这种漏洞在现代环境中已较少见但历史代码中可能存在。路径规范化前的点号....//或....\/。某些蹩脚的过滤逻辑可能只替换一次../那么....//在经过一次替换或规范化后可能变成../。操作系统特性差异Windows除了../还可以使用..\。Windows路径不区分大小写且支持网络路径如\\192.168.1.1\share。此外Windows下的“文件流”特性也可能被利用。非标准分隔符在某些上下文或配置错误的解析器中反斜杠\也可能被当作目录分隔符。理解这些绕过手法的意义在于你在设计防御方案时不能只做简单的字符串匹配或替换必须建立一个多层次、基于规范化结果校验的防御体系。3. 手工探测与利用路径遍历漏洞在自动化工具大行其道的今天手工探测漏洞的能力依然不可替代。它能帮助你理解漏洞的上下文发现工具无法识别的变异型漏洞。3.1 信息收集与参数定位首先你需要识别所有可能的攻击面爬取与观察使用浏览器或爬虫工具浏览目标应用重点关注任何带有“下载”、“查看”、“打开”、“加载”、“导入”、“导出”、“日志”、“备份”等字样的功能链接。分析请求打开浏览器开发者工具F12的“网络”选项卡操作上述功能观察产生的HTTP请求。寻找GET/POST参数中可能包含文件路径的键名如file,filename,path,dir,document,image,load,pdf,url,page等。FUZZ字典辅助可以准备一个常见文件路径参数名的字典在模糊测试时使用。3.2 基础探测步骤假设我们发现一个疑似端点https://target.com/download?filenameuser_guide.pdf测试基础遍历尝试filename../../../etc/passwd尝试filename../../../../etc/passwd多级回溯尝试filename/etc/passwd绝对路径观察响应如果返回403 Forbidden、400 Bad Request可能意味着路径存在但被拒绝访问这本身就是一个线索。如果返回404 Not Found可能是路径不对或文件不存在。如果返回200 OK且内容长度发生变化并出现了类似root:x:0:0:...的文本那么漏洞很可能存在。测试编码绕过如果基础../被拦截尝试URL编码filename%2e%2e%2f%2e%2e%2f%2e%2e%2fetc%2fpasswdfilename..%2f..%2f..%2fetc%2fpasswd尝试双重编码。测试空字节截断针对老旧系统如果发现程序会自动添加后缀如filenametest实际访问test.pdf则尝试filename../../../etc/passwd%00filename../../../etc/passwd%00.jpg3.3 利用漏洞读取敏感文件一旦确认漏洞存在下一步就是系统地读取敏感信息为后续可能的渗透做准备。以下是一份Linux/Windows系统下的关键文件清单Linux/Unix 系统/etc/passwd用户账户信息常可读用于枚举用户。/etc/shadow加密后的用户密码哈希需root权限但若Web服务以高权限运行可能可读。/etc/hosts主机名映射。/proc/version/etc/issue系统版本信息。/home/username/.bash_history用户命令历史可能包含密码、密钥等信息。Web应用配置文件如/var/www/html/config.phpdatabase.yml.envweb.configapplication.properties等这些文件常包含数据库密码、API密钥。应用日志文件可能包含调试信息、访问日志、错误日志。~/.ssh/id_rsa用户的SSH私钥。Windows 系统C:\Windows\System32\drivers\etc\hostsC:\boot.ini旧系统C:\Windows\win.iniC:\Windows\System32\config\SAMSAM数据库通常被锁定Web应用目录下的web.configappsettings.json等。特定应用的配置文件路径。实操心得读取文件时不要只满足于/etc/passwd。尝试构造路径读取Web应用自身的源代码如../index.php、配置文件、日志文件往往能获得更直接、更有价值的信息例如数据库连接字符串、后台管理路径、硬编码的密钥等这些是通往下一步的“金钥匙”。3.4 利用漏洞写入文件更危险如果漏洞点是一个文件上传、模板编辑或任何涉及“写”操作的功能路径遍历就可能升级为“任意文件写入”进而可能导致“远程代码执行”。例如一个允许用户保存模板的功能/saveTemplate?pathheader.htmlcontenth1Hello/h1如果path参数未过滤攻击者可以提交path../../../var/www/html/shell.phpcontent?php system($_GET[‘cmd’]);?这将在Web根目录写入一个Webshell攻击者即可通过访问https://target.com/shell.php?cmdid来执行任意系统命令。写入位置的技巧Web可访问目录写入到Web服务器的文档根目录或其子目录确保可以通过HTTP访问到。计划任务目录Linux的/var/spool/cron/crontabs/特定用户或/etc/cron.d/ Windows的计划任务目录。写入一个计划任务文件等待执行。启动脚本目录如/etc/profile.d/.bashrc等在用户登录时执行。临时目录结合其他漏洞如文件包含、命令注入来执行。4. 自动化工具辅助测试与高级利用手工测试是基础但在大规模测试或需要深度模糊测试时自动化工具能极大提升效率。4.1 使用Burp Suite进行测试Burp Suite是Web安全测试的瑞士军刀其Intruder模块非常适合进行路径遍历的模糊测试。抓取请求在浏览器中代理设置好后操作可疑功能Burp会捕获到请求。发送至Intruder右键点击请求选择“Send to Intruder”。设置攻击位置在Intruder的“Positions”标签页清除所有自动标记然后手动选中你想要测试的参数值如user_guide.pdf点击“Add §”。配置Payload切换到“Payloads”标签页。在“Payload Options”中你可以加载一个路径遍历的字典。Kali Linux中自带的/usr/share/wordlists/dirbuster/directory-list-lowercase-2.3-medium.txt并不专门针对路径遍历。更好的选择是SecLists项目中的字典例如/usr/share/seclists/Fuzzing/LFI/LFI-Jhaddix.txt它包含了各种绕过Payload。你也可以使用“Payload type”为“Runtime file”动态生成Payload或者使用“Custom iterator”来组合前缀如../../../和后缀如etc/passwdwindows/win.ini。设置资源池与线程在“Resource Pool”中调整线程数避免对目标服务器造成过大压力。开始攻击并分析结果点击“Start attack”。攻击开始后重点关注“Length”和“Status”列。与基线响应请求正常文件时的响应长度和状态码差异巨大的响应都值得仔细查看。通常成功的遍历访问会导致响应状态码为200且长度与正常文件不同。双击该请求在响应Response面板查看具体内容确认是否读取到了目标文件。4.2 结合其他漏洞形成攻击链单纯的路径遍历读取文件危害有限但一旦与其他漏洞结合就能产生“化学反应”危害倍增。路径遍历 文件包含 远程代码执行这是经典组合。如果存在本地文件包含漏洞但无法直接上传Webshell可以先通过路径遍历将恶意代码写入服务器的某个临时文件或日志文件然后通过文件包含漏洞去包含这个文件从而执行代码。路径遍历获取配置文件 - 数据库入侵通过遍历读取到数据库配置文件获取连接IP、端口、用户名、密码。随后直接连接数据库进行拖库、篡改等操作。路径遍历读取源码 - 白盒审计通过遍历读取Web应用的PHP、JSP、Python等源代码进行白盒代码审计可能发现更隐蔽的逻辑漏洞、反序列化漏洞等。路径遍历读取日志 - 注入攻击如果应用将用户输入如User-Agent, Referer记录到日志文件中攻击者可以先通过路径遍历找到日志文件路径然后在请求中注入恶意代码如PHP代码再通过路径遍历去包含这个日志文件实现代码执行。这需要应用有文件包含漏洞配合。路径遍历覆盖关键文件如果可以任意文件写入可以直接覆盖系统的关键脚本、应用的核心业务文件造成服务中断或植入后门。5. 从根源防御路径遍历攻击防御路径遍历攻击核心原则是“永远不要信任用户输入”并实施“白名单”策略。以下是分层防御的具体措施。5.1 输入验证使用白名单而非黑名单这是最重要的一环。黑名单过滤../..\等永远会落后于攻击者的绕过技巧。理想做法维护一个允许访问的文件名或文件ID的白名单。用户只能从预定义的列表中选择文件。实现示例后端存储文件时使用随机生成的UUID作为文件名如a1b2c3d4.pdf并在数据库中记录UUID与原始文件名的映射。前端只传递UUID。后端通过UUID从数据库查询到存储的真实路径再进行文件操作。这样用户输入完全与文件系统路径解耦。次选方案如果必须允许用户输入文件名则使用严格的白名单正则表达式进行校验。示例Pythonimport re allowed_filename_pattern re.compile(r^[a-zA-Z0-9_\-]\.(pdf|docx|jpg)$) if not allowed_filename_pattern.match(user_input_filename): raise ValueError(Invalid filename)这个正则只允许字母、数字、下划线、连字符组成的文件名并且后缀必须是pdfdocx或jpg。../之类的字符根本无法通过校验。5.2 规范化与路径校验在无法使用严格白名单的复杂场景下必须对最终路径进行严格校验。规范化路径使用编程语言提供的标准库函数将路径中的... 多余的/等解析掉得到绝对路径。Python:os.path.normpath() 然后结合os.path.abspath()。Java:Path.normalize().toAbsolutePath()。PHP:realpath()注意其行为。校验是否在允许的目录内将规范化后的绝对路径与预设的允许访问的基础目录的绝对路径进行比较确保前者是后者的子目录。关键函数确保使用正确的函数检查子目录关系避免字符串比较的陷阱。Python示例import os base_dir os.path.abspath(/var/www/safe_dir) user_input subdir/file.txt # 拼接并规范化 full_path os.path.normpath(os.path.join(base_dir, user_input)) # 关键校验确保规范化后的路径以base_dir开头 if not full_path.startswith(base_dir os.sep) and full_path ! base_dir: raise PermissionError(Access denied: Path traversal attempt detected.) # 安全检查通过操作full_path这里使用startswith(base_dir os.sep)是为了防止“目录穿越”攻击。例如base_dir/safe 攻击者输入/safe../etc/passwd 拼接后为/safe/safe../etc/passwd 规范化后可能变成/etc/passwd。但如果我们要求路径必须以/safe/开头这个攻击就会被阻断。5.3 运行环境与权限加固最小权限原则运行Web服务的操作系统用户如www-datanginx应该拥有尽可能低的权限。绝对不能以root身份运行。确保该用户只能读取Web应用必要的目录和文件对可写目录如上传目录的权限要严格控制最好设置为不可执行脚本。文件系统权限上传目录应设置为755所有者读写执行 组和其他只读执行或更严格并且通过Web服务器配置如Nginx的location块中设置deny allfor.php禁止直接执行该目录下的脚本文件。容器化与沙箱使用Docker等容器技术将应用隔离在独立的命名空间中即使存在漏洞攻击者能访问的范围也被限制在容器内部。Web服务器配置正确配置Web服务器避免将敏感目录暴露为Web可访问。例如Nginx/Apache不要将整个/或/home目录设为根目录。5.4 安全开发流程与测试安全编码规范在团队中制定并推行安全编码规范明确禁止未经校验的路径拼接操作。代码审计将路径遍历作为代码审计SAST和渗透测试DAST的必查项。使用自动化工具扫描并结合人工复审。依赖库安全及时更新所使用的Web框架、文件处理库这些库的更新可能会修复相关的路径处理安全问题。错误信息处理当路径遍历攻击被拦截或文件不存在时返回统一的、信息模糊的错误页面如“文件未找到”避免泄露服务器真实的路径信息。6. 实战排查与应急响应当你怀疑或已经确认系统存在路径遍历漏洞时应该怎么做6.1 漏洞排查清单全局搜索在代码库中搜索高危函数和模式。PHP:includerequirefile_get_contentsfopen 以及$_GET$_POST$_REQUEST与这些函数的结合使用。Java:FileInputStreamFileReadernew File() 以及从HttpServletRequest.getParameter()获取的参数直接用于这些构造。Python:open()os.open() 以及从request.argsrequest.form获取的参数直接用于文件操作。Node.js:fs.readFilefs.createReadStream 以及从req.queryreq.body获取的参数直接使用。审查文件操作逻辑对搜索到的结果进行人工审计检查是否存在未经验证的用户输入直接拼接成文件路径的情况。测试验证对修改后的代码或补丁构造包含各种绕过手法的Payload进行测试确保防御措施有效。6.2 应急响应步骤立即隔离如果漏洞正在被利用考虑暂时禁用相关功能接口或在WAF/网关层面设置紧急规则拦截包含特定序列../..\ 编码形式等的请求。评估影响检查Web服务器、数据库、系统日志寻找异常访问记录。根据漏洞可能被访问的目录评估哪些敏感文件可能已泄露如配置文件、源码、数据文件。如果存在写入漏洞检查Web目录、计划任务目录等关键位置是否有新增的陌生文件。修复漏洞按照前述的防御方案立即修复代码。优先采用“白名单”或“映射ID”方案其次采用“规范化路径校验”方案。更改凭据如果怀疑数据库连接密码、API密钥、SSH密钥等敏感信息可能已泄露立即进行轮换更改。监控与复盘修复后加强监控观察是否还有攻击尝试。对事件进行复盘完善安全开发流程避免同类问题再次发生。路径遍历漏洞如同一扇忘记上锁的后门看似不起眼却可能通向整个系统的心脏。防御它并不需要高深的技术需要的仅仅是严谨的态度和对“输入即不可信”这一安全铁律的坚守。在每一次代码编写、每一次功能设计时都多问一句“用户如果在这里输入../../../会发生什么”就能将绝大多数此类风险扼杀在萌芽之中。真正的安全就藏在这些细微之处的谨慎处理之中。