目录遍历漏洞的本质是Web服务器或应用在解析用户请求时,未能严格过滤“../”这类路径跳转字符,导致攻击者可以突破Web根目录限制,读取服务器上的任意文件。修复这个漏洞不能只靠表面拦截,必须从权限模型、解析逻辑、部署架构三个层面同时下手。

最直接的修复位置是Web服务器配置。以Nginx为例,很多人只配置了location匹配规则,却忽略了URI规范化阶段的路径处理。攻击者常用编码绕过,比如%2e%2e%2f代表“../”,或者双编码%252e%252e%252f。Nginx默认在收到请求时会做一次URL解码,如果你的应用层又做了一次解码,就可能被绕过。正确做法是在server块中显式拒绝包含编码路径特征的请求:

location ~* (%2e%2e|%252e|\.\./|\.\.\\|%c0%ae|%uff0e) {
    return 403;
}

但这条规则只能作为第一层防线。真正可靠的修复是限制Web进程的系统权限。Linux下运行Nginx或Apache的worker进程,应当使用独立低权限账户,并且该账户对网站根目录之外的路径没有任何读权限。很多人用root跑Web服务,一旦出现目录遍历,攻击者直接能读/etc/passwd、数据库配置文件甚至SSH私钥。正确做法是:Web目录属主为部署用户,Web进程用户只保留读和执行权限,其他系统目录全部拒绝访问。可以用setfacl做精细化控制:

setfacl -R -m u:www-data:rx /var/www/site
setfacl -R -m u:www-data:--- /etc /home /root /var/log

应用层修复同样关键。很多目录遍历漏洞并非出在Web服务器,而是应用代码中直接拼接用户输入作为文件路径。例如PHP中常见的文件下载功能:

$file = $_GET['file'];
readfile("/var/www/uploads/" . $file);

攻击者传入file=../../../../etc/passwd即可读取系统文件。修复这类问题不能只靠过滤“../”,因为过滤逻辑容易被编码、双写、路径分隔符差异绕过。正确做法是使用白名单映射:前端只传文件ID或哈希值,后端根据ID在数据库或固定映射表中查找真实路径,用户输入永远不直接参与路径拼接。如果必须使用文件名,则先用basename()取出纯文件名,再用realpath()校验解析后的绝对路径是否仍位于预期目录内:

$base = realpath('/var/www/uploads');
$target = realpath($base . '/' . basename($_GET['file']));
if ($target === false || strpos($target, $base) !== 0) {
    http_response_code(403);
    exit;
}
readfile($target);

Java、Python、Node.js等语言同理。核心原则是:用户输入只能作为索引键,不能作为路径片段。任何需要文件操作的接口,都要做路径规范化后的前缀校验。

除了代码和服务器配置,还要关注框架和中间件的默认行为。某些老旧版本的Tomcat、WebLogic、Resin自带目录浏览功能,即使没有遍历漏洞,也会直接列出目录结构。这类信息泄露往往被忽略,但攻击者可以借此摸清站点文件布局,为进一步利用做准备。修复方法是关闭目录索引:Tomcat中在web.xml里将listings参数设为false;Nginx中确保没有启用autoindex on;Apache中移除Indexes选项。

防护加固方面,第一件事是部署Web应用防火墙规则。针对目录遍历的WAF规则不能只匹配“../”字符串,要覆盖常见编码变体:URL编码、双重编码、Unicode全角字符、反斜杠、空字节截断等。但WAF只能作为辅助手段,因为规则永远滞后于绕过手法。更有效的加固是在应用前部署反向代理,由代理层统一做URI规范化校验,将非标准编码的请求直接拒绝,确保到达后端的请求路径已经过严格清洗。

日志监控是很多人忽视的环节。目录遍历攻击通常伴随大量404或403响应,因为攻击者需要不断尝试不同深度的“../”组合。如果在短时间内同一IP出现大量包含“../”、“%2e”、“%c0%ae”等特征的请求,即使全部被拦截,也应当触发告警。建议在Nginx或Apache日志中记录原始请求URI,并接入日志分析平台,对路径穿越特征做实时统计。发现扫描行为后,可以在防火墙层面临时封禁源IP,同时排查是否有成功读取文件的迹象。

容器化部署环境中,目录遍历的风险模型有所变化。容器本身提供了一定隔离,但如果容器内Web进程以root运行,攻击者读取到容器内敏感文件后,可能进一步利用挂载卷逃逸到宿主机。因此容器内也要坚持非root运行,并且挂载卷只给必要目录,不要挂载整个根文件系统。Kubernetes中可以用PodSecurityPolicy或SecurityContext强制限制文件系统只读、禁止特权模式。

还有一个容易被忽略的点是静态资源服务器。很多团队把静态文件直接放在Nginx下,认为没有动态代码就不会有目录遍历。实际上,如果Nginx配置了alias或root指向不当,攻击者可以通过构造URL访问到root目录之外的文件。例如配置alias /var/www/site/static/; 但请求/static../config.php时,部分旧版本Nginx会解析到/var/www/site/config.php。修复方法是升级Nginx到稳定版本,并在alias路径末尾确保有斜杠,同时避免使用变量拼接root路径。

对于已经出现目录遍历漏洞的系统,修复后必须做全面排查。攻击者可能已经读取了配置文件、数据库密码、源码备份等敏感信息。建议检查最近一段时间的访问日志,重点关注包含路径穿越特征的请求及其响应状态码。如果发现成功读取敏感文件的迹象,应当立即轮换所有密钥、数据库密码、API令牌,并检查是否有后续的异常登录或数据外传行为。只修复漏洞而不处理可能已泄露的信息,等于给攻击者留了后门。

长期防护方面,建议建立一套文件访问基线。所有涉及文件读取、下载、预览的接口,统一走一个经过安全审计的文件服务模块,禁止各业务线自行实现文件操作。该模块内部强制做路径白名单校验、权限检查、访问频率限制。同时定期对线上系统做路径穿越专项测试,覆盖常见编码绕过、大小写变体、Unicode归一化差异等场景。安全测试不能只依赖自动化扫描器,因为很多绕过手法需要结合具体业务逻辑才能发现。

目录遍历漏洞的修复难度并不高,难的是彻底清除所有可能的路径拼接点。服务器配置、应用代码、框架默认行为、容器挂载、静态资源映射,每一层都可能成为突破口。只有把权限最小化、输入白名单化、路径规范化校验这三件事同时做到位,才能从根本上消除这类风险。