除了 ../ 之外,还有其他序列会在 *nix 或 Windows 中被解释为目录遍历吗?

信息安全 应用安全 开发 网络服务器 目录遍历 路径注入
2021-09-01 10:12:12

一个常见的漏洞是 Web 应用程序接受文件系统路径作为请求参数,然后对指定路径执行一些操作。例如,检索文件并将其返回给用户,或者甚至可能写入/删除文件。这可能允许恶意用户访问他们不应访问的文件,例如源代码、密码文件等。

即使您预先添加基本路径,这也可能是一个问题,因为攻击者可以使用../(*nix) 和..\(Windows) 等目录遍历序列从基本路径向上遍历并进入受限制的目录和文件。

那么,一般的想法是要么彻底禁止任何这样的遍历序列,要么“规范化”包含这些序列的路径,然后检查它们是否仍然落在基本路径内。

从我的理解,试图在请求参数黑名单遍历序列是困难的,因为有备用网址和Unicode编码(例如%2e%2e%2f,和许多许多其他)最终可能会由Web服务器被解释为../..\

但是,如果我们在网络服务器(例如,Apache)接收到路径并传递给我的应用程序之后对其进行规范化,那么替代编码是否仍然是一个问题例如,使用这些规范化规则

我的理由是,无论网络服务器接收%2e%2e%2f并将其解码为../,还是网络服务器直接接收../,规范化算法都会../在检查基本目录之前查看并解析/过滤它。即使攻击者使用类似 的双重编码%252e%252e%252f,它也会被解码为%2e%2e%2f,操作系统/文件系统将逐字处理。

但是,在这个问题中,它表明:

但是,如果 Web 服务器正在提供文件并且解码 unicode 是在防止目录遍历的检查之后完成的,或者由操作系统完成的稍有不同,则此攻击可能会通过过滤器,从而允许攻击起作用。

因此,换句话说,是否有任何已知的字符序列可以使其通过 Web 服务器的解码和上述规范化例程(处理../..\),可以被操作系统或较低级别的文件处理函数解释为目录遍历?

例如,在 PHP 中:

$base = "/path/to/allowed/directory/";
$path = $_GET['path'];

$normalizedPath = normalize($path);   // normalize will remove or resolve ../ and ..\
$fullPath = $base . $normalizedPath;

echo file_get_contents($fullPath);
2个回答

在 Windows 和 Unix 上 -没有可能存在使用不同路径分隔符的晦涩操作系统。

为了安全地处理编码,有一个简单的规则:在进行清理之前完全解码如果你不这样做,你的消毒可以被规避。想象一个应用程序open(urldecode(normalize(path)))如果路径包含../然后规范化删除它。但是如果它包含%2e%2e%2f然后 normalize 将什么也不做,并且 urldecode 会将其转换为../. 此错误导致了许多现实世界的漏洞,包括众所周知的IIS unicode 错误

有时会出现的另一个问题是嵌套序列假设你的 normalize 函数是path.replaceAll('../', ''). 这可以通过尝试来规避....//——内部../被移除,离开../解决方案是要么完全拒绝包含禁止序列的字符串,要么递归地应用规范化函数。

还有其他字符可能会在路径中产生令人惊讶的结果。高级语言的字符串中通常允许空字节,但是当它传递给 C 库时,空字符串是一个终止像这样的文件名evil.php%00.jpg可以绕过文件扩展名检查。还有IIS 分号错误

通常,文件名不是存放不受信任数据的好地方。存在二级攻击的可能性,其中读取目录列表的其他进程存在漏洞。列出文件的网页中可能存在跨站点脚本;存在恶意文件名可以利用的 Windows 资源管理器漏洞;通过转义序列攻击 Unix shell 是最近的一个问题。相反,我建议将用户提供的文件名存储在数据库中,并将文件名作为主键。

利用 Unicode,可以将其编码\/多字节字符。如果字符串比较函数不支持 unicode,则可能存在允许这些字符通过的错误。

Wikipedia 有一个与 Windows 服务器上的旧攻击有关的部分:

当 Microsoft 在其 Web 服务器中添加 Unicode 支持时,他们../的代码中引入了一种新的编码方式,从而避免了他们在防止目录遍历方面的尝试。

多个百分比编码,例如

  • %c1%1c
  • %c0%af

翻译成/\字符。

从技术上讲,当涉及到目录遍历时,这仍然使用斜杠字符,它不是真正的单字节字符,可能会混淆某些代码。

我相信避免此类字符的最佳建议是禁止文件系统路径中的任何字符,但 ASCII 字符的安全子集除外。您还可以同时回避某些操作系统和文件系统中允许字符的其他问题。