路径遍历漏洞是Web安全领域中最常见且危害严重的漏洞之一,攻击者通过构造带有../或..\等特殊序列的输入,可以突破文件路径限制,读取服务器上任意文件,包括配置文件、密码文件甚至系统敏感数据。有效防御路径遍历漏洞的核心在于对用户输入进行严格的路径规范化处理,并实施最小权限的文件访问控制,而非简单的黑名单过滤。
路径遍历漏洞的本质是程序在处理用户提供的文件路径时,未对路径中的特殊字符(如../)进行充分过滤或规范化,导致攻击者可以跳出预期的文件目录范围。例如,一个允许用户查看图片的接口/download?file=image.png,如果未做防护,攻击者可传入../../../etc/passwd来读取系统中的敏感文件。据OWASP《Web应用安全十大风险》报告显示,路径遍历漏洞在各类漏洞中排名前10,且在实际渗透测试中,约30%的Web应用存在某种形式的路径遍历风险。
攻击者为了绕过开发者的简单防护,发展出多种绕过手法,以下列举最常用的几种。
开发者可能仅过滤了../字符串,但攻击者可以对斜杠和点进行URL编码,例如%2e%2e%2f(对应../)或%2e%2e%5c(对应..\)。如果服务器对输入进行了URL解码,就会绕过简单的字符串匹配。更高级的编码包括双重编码(%252e%252e%252f),当程序对输入进行两次解码时,第一次解码得到%2e%2e%2f,第二次解码才得到../。
当程序允许用户指定文件路径但仅检查是否包含../时,攻击者可以直接使用绝对路径,如/etc/passwd,如果程序没有强制限制目录起始点,攻击者就能直接读取任意文件。例如,/download?file=/etc/passwd。
在旧版PHP或Java应用中,攻击者可以在路径后添加空字节(%00)来截断预期扩展名。例如,假设程序强制在用户输入后追加.txt,攻击者可传入../../../etc/passwd%00,服务器在处理时可能忽略%00之后的内容,从而读取/etc/passwd文件。不过这种手法在现代语言中已较少奏效,但在某些C语言编写的底层库中依然存在。
利用不同编码表示相同字符,如在IIS服务器中,..%c0%af可以绕过基于ASCII的过滤,因为%c0%af在UTF-8解码后可能被解释为/。类似地,..%c1%9c可表示..\。这种绕过手法依赖于服务器的编码处理差异。
| 绕过手法 | 示例Payload | 适用场景 | 防护难度 |
|---|---|---|---|
| 编码绕过 | %2e%2e%2f | 仅做字符串匹配的防护 | 低 |
| 双重编码 | %252e%252e%252f | 单次解码的防护逻辑 | 中 |
| 绝对路径 | /etc/passwd | 未限制目录起始点 | 低 |
| 空字节截断 | ../../../etc/passwd%00 | 旧版PHP/Java | 高(现代框架已修复) |
| Unicode变体 | ..%c0%af | IIS等特定服务器 | 中 |
防御路径遍历漏洞需要从多个层面入手,单一措施难以完全防护。
对用户输入的文件路径进行规范化处理,将路径中的../、..\等序列解析为实际路径,然后检查规范化后的路径是否以允许的根目录开头。例如,在Java中可以使用File.getCanonicalPath(),在Python中使用os.path.realpath()或os.path.abspath()。之后,验证该路径是否位于预设的允许目录内。如果用户输入的文件名应该是固定的,则应使用白名单机制,只允许预定义的文件名列表。
Web应用程序运行时应使用最小权限的操作系统账户,例如只允许读取特定目录(如/var/www/uploads),即使攻击者绕过路径限制,也无法读取/etc/passwd等系统文件。此外,数据库连接、配置文件等敏感文件应放置在Web根目录之外,避免被直接访问。
不建议使用字符串拼接来构建文件路径,而是使用框架提供的安全文件访问API。例如,使用java.nio.file.Paths而不是直接拼接字符串。很多现代Web框架(如Spring Boot、Django、Express)都提供了对文件下载的安全封装,应优先使用官方推荐的方法。
在执行任何路径操作前,对用户输入进行充分的验证:拒绝包含../、..\、/、\等字符的输入,除非业务确实需要。同时,对URL编码进行解码后再次验证,防止双重编码绕过。对于文件下载功能,强烈建议使用数据库中的ID或哈希值来映射真实文件路径,而不是直接让用户提供文件名。
假设一个PHP应用提供文件下载功能:download.php?file=report.pdf。攻击者尝试../../../etc/passwd,服务器返回了/etc/passwd内容。修复方案如下:
$allowedDir = '/var/www/uploads/';
$userInput = $_GET['file'];
// 规范化路径
$realPath = realpath($allowedDir . $userInput);
// 检查是否在允许目录内
if ($realPath === false || strpos($realPath, $allowedDir) !== 0) {
die('Invalid file');
}
readfile($realPath);这段代码先拼接用户输入到允许目录,然后使用realpath()解析符号链接和../序列,得到真实物理路径;最后检查该路径是否以允许目录开头。如果用户输入包含../../../etc/passwd,realpath会解析为/etc/passwd,而该路径不以/var/www/uploads/开头,因此拒绝访问。
路径遍历漏洞虽然常见,但通过合理的防御措施可以完全避免。核心在于:使用路径规范化、白名单检查、最小权限原则,同时避免直接拼接用户输入。开发者应假设所有用户输入都是恶意的,并在框架层面做好安全兜底。据Veracode《应用安全状态报告》显示,经过规范化处理的路径遍历漏洞修复率可达95%以上,而仅靠黑名单过滤的修复率不足40%。因此,选择正确的防御策略是保障Web应用安全的关键。
评论
加载中...