PHP Open_basedir的深度绕过技术：利用`chdir()`和`realpath()`的缓存特性

admin
Mon, 24 Nov 2025 06:37:26 +0000
PHP, basedir, open, php

PHP Open_basedir 深度绕过技术：利用 chdir() 和 realpath() 的缓存特性 大家好，今天我们来深入探讨一个在 PHP 安全领域中比较有趣的话题：Open_basedir 的深度绕过。Open_basedir 是一种安全机制，旨在限制 PHP 脚本可以访问的文件系统目录。然而，由于其自身的实现方式以及 PHP 解释器的一些特性，Open_basedir 有时可以被绕过。今天我们将重点关注一种绕过方式，即利用 chdir() 和 realpath() 的缓存特性。 Open_basedir 简介 Open_basedir 是 PHP 中的一个配置选项，用于指定 PHP 脚本可以访问的文件系统目录列表。其主要目的是防止恶意脚本访问服务器上的敏感文件或目录，从而提高服务器的安全性。 例如，我们可以设置 open_basedir = /var/www/html:/tmp，这意味着 PHP 脚本只能访问 /var/www/html 和 /tmp 目录及其子目录。任何尝试访问其他目录的操作都会被 PHP 解释器阻止，并抛出一个警告。 Open_basedir 通常在 …

继续阅读“PHP Open_basedir的深度绕过技术：利用`chdir()`和`realpath()`的缓存特性”

The post PHP Open_basedir的深度绕过技术：利用`chdir()`和`realpath()`的缓存特性 first appeared on 智猿学院-前后端，数据库，人工智能，云计算等领域前沿技术讲座.

PHP Open_basedir 深度绕过技术：利用 chdir() 和 realpath() 的缓存特性

大家好，今天我们来深入探讨一个在 PHP 安全领域中比较有趣的话题：Open_basedir 的深度绕过。Open_basedir 是一种安全机制，旨在限制 PHP 脚本可以访问的文件系统目录。然而，由于其自身的实现方式以及 PHP 解释器的一些特性，Open_basedir 有时可以被绕过。今天我们将重点关注一种绕过方式，即利用 chdir() 和 realpath() 的缓存特性。

Open_basedir 简介

Open_basedir 是 PHP 中的一个配置选项，用于指定 PHP 脚本可以访问的文件系统目录列表。其主要目的是防止恶意脚本访问服务器上的敏感文件或目录，从而提高服务器的安全性。

例如，我们可以设置 open_basedir = /var/www/html:/tmp，这意味着 PHP 脚本只能访问 /var/www/html 和 /tmp 目录及其子目录。任何尝试访问其他目录的操作都会被 PHP 解释器阻止，并抛出一个警告。

Open_basedir 通常在 php.ini 文件中进行配置，也可以通过 .htaccess 文件或 ini_set() 函数在运行时进行设置。

配置方式示例：

php.ini:

open_basedir = /var/www/html:/tmp

.htaccess:

php_value open_basedir "/var/www/html:/tmp"

PHP 代码:

ini_set('open_basedir', '/var/www/html:/tmp');

绕过 Open_basedir 的必要性

尽管 Open_basedir 是一种有效的安全措施，但它并非绝对安全。历史上，已经发现了一些绕过 Open_basedir 的技术。这些绕过技术利用了 PHP 解释器自身的漏洞、配置不当或一些不常见的函数行为。

了解这些绕过技术对于安全工程师和开发人员来说至关重要。这可以帮助他们更好地配置和维护 PHP 环境，及时发现和修复潜在的安全漏洞，从而提高 Web 应用程序的安全性。

chdir() 和 realpath() 的作用

在深入探讨绕过技术之前，我们需要了解 chdir() 和 realpath() 这两个 PHP 函数的作用。

chdir(): chdir() 函数用于改变 PHP 脚本的当前工作目录。例如，chdir('/tmp') 会将当前工作目录更改为 /tmp。

realpath(): realpath() 函数用于将一个相对路径转换为绝对路径，并解析所有符号链接和 . 或 .. 路径片段。例如，如果当前工作目录是 /var/www/html，那么 realpath('./index.php') 可能会返回 /var/www/html/index.php。

这两个函数在文件系统操作中非常常用，但它们的行为也可能会被利用来绕过 Open_basedir。

缓存机制与 Open_basedir 绕过

PHP 在处理文件路径时，会使用内部缓存来提高性能。realpath() 的结果会被缓存起来，这意味着如果多次调用 realpath() 函数，只要路径没有发生改变，PHP 解释器会直接返回缓存的结果，而不会每次都进行实际的文件系统查找。

此外，chdir() 也会影响 realpath() 的行为。当使用 chdir() 改变当前工作目录后，后续的 realpath() 调用会基于新的工作目录进行解析。

结合这两个特性，我们可以设计一种绕过 Open_basedir 的方法：

1. 进入 Open_basedir 允许的目录： 首先，使用 chdir() 进入一个 Open_basedir 允许访问的目录。

2. 利用相对路径： 然后，使用相对路径构造一个指向 Open_basedir 限制目录的路径。

3. 触发缓存： 通过某种方式，让 realpath() 缓存这个相对路径的解析结果。

4. 绕过限制： 在后续的文件操作中，利用缓存的路径来访问 Open_basedir 限制的目录。

深度绕过的原理与步骤

这种绕过方式之所以被称为“深度绕过”，是因为它利用了 realpath() 在解析相对路径时的深度解析能力。即使相对路径包含多层 ../ 目录，realpath() 仍然可以正确地解析出最终的绝对路径。

绕过的核心在于 realpath() 的缓存机制和对相对路径的解析。

以下是一个具体的绕过示例：

假设 open_basedir = /var/www/html，我们想要访问 /etc/passwd 文件。

代码示例：

<?php

ini_set('open_basedir', '/var/www/html');

$allowed_dir = '/var/www/html';
$target_file = '/etc/passwd';

// 1. 进入 Open_basedir 允许的目录
chdir($allowed_dir);

// 2. 构造相对路径
$relative_path = '../../../../../../../../../../etc/passwd'; // 足够多的 ../ 确保到达根目录

// 3. 使用 realpath() 解析相对路径并缓存结果
$absolute_path = realpath($relative_path);

// 4. 尝试读取文件
if ($absolute_path) {
    echo "Absolute path: " . $absolute_path . "n";
    $content = @file_get_contents($absolute_path);
    if ($content) {
        echo "Content of /etc/passwd:n";
        echo $content;
    } else {
        echo "Failed to read /etc/passwdn";
    }
} else {
    echo "Failed to resolve the pathn";
}

?>

代码解释：

1. ini_set('open_basedir', '/var/www/html'); 设置 Open_basedir 为 /var/www/html。

2. chdir($allowed_dir); 将当前工作目录更改为 /var/www/html，这是 Open_basedir 允许的目录。

3. $relative_path = '../../../../../../../../../../etc/passwd'; 构造一个相对路径，通过多层 ../ 返回到根目录，然后访问 /etc/passwd 文件。

4. $absolute_path = realpath($relative_path); 使用 realpath() 解析相对路径，并将其缓存。

5. file_get_contents($absolute_path); 尝试读取 /etc/passwd 文件。由于 realpath() 已经缓存了 /etc/passwd 的绝对路径，因此可以绕过 Open_basedir 的限制。

流程图：

[开始] --> [设置 Open_basedir]
[设置 Open_basedir] --> [chdir() 进入允许目录]
[chdir() 进入允许目录] --> [构造相对路径]
[构造相对路径] --> [realpath() 解析并缓存路径]
[realpath() 解析并缓存路径] --> [尝试读取文件]
[尝试读取文件] --> [结束]

注意事项：

这种绕过方式的成功与否取决于 PHP 的版本和配置。在某些版本中，realpath() 可能会在遇到 Open_basedir 限制时返回 false。

file_get_contents() 函数前的 @ 符号用于抑制错误输出。

实际环境中，需要根据目标服务器的目录结构调整相对路径。

深入分析：缓存机制的实现细节

为了更好地理解这种绕过方式，我们需要深入了解 realpath() 缓存机制的实现细节。

PHP 内部维护一个 realpath_cache，用于存储 realpath() 的结果。这个缓存是一个关联数组，Key 是原始路径，Value 是解析后的绝对路径。

当调用 realpath() 函数时，PHP 解释器首先会检查 realpath_cache 中是否存在该路径的缓存。如果存在，则直接返回缓存的结果；否则，执行实际的文件系统查找，并将结果添加到缓存中。

realpath_cache 的大小和过期时间可以通过 realpath_cache_size 和 realpath_cache_ttl 两个配置选项进行控制。

配置选项：

配置选项 | 描述 | 默认值
realpath_cache_size | 指定 realpath_cache 的大小，单位是字节。这个值决定了缓存可以存储的路径数量。 | 4096K
realpath_cache_ttl | 指定 realpath_cache 中缓存项的过期时间，单位是秒。这个值决定了缓存项在多长时间后会被自动清除。 | 120

了解这些配置选项可以帮助我们更好地控制 realpath() 的行为，从而提高绕过的成功率。

防御措施：如何避免被绕过

虽然 Open_basedir 存在被绕过的风险，但我们仍然可以采取一些措施来提高安全性：

1. 使用最新的 PHP 版本： PHP 的新版本通常会修复已知的安全漏洞，包括 Open_basedir 的绕过漏洞。

2. 配置 Open_basedir 时要尽可能严格： 仅允许访问必要的目录，避免过度开放权限。

3. 禁用不必要的函数： 禁用可能被利用来绕过 Open_basedir 的函数，例如 symlink()、popen() 等。

4. 使用安全的代码审计工具： 定期进行代码审计，发现潜在的安全漏洞。

5. 使用 Web 应用防火墙 (WAF)： WAF 可以检测和阻止恶意请求，包括尝试绕过 Open_basedir 的请求。

6. 使用 chroot 环境： 将 PHP 运行在 chroot 环境中，可以进一步限制文件系统的访问范围。

防御措施表：

防御措施 | 描述
使用最新的 PHP 版本 | 及时更新 PHP 版本，修复已知的安全漏洞。
严格配置 Open_basedir | 仅允许访问必要的目录，避免过度开放权限。
禁用不必要的函数 | 禁用可能被利用来绕过 Open_basedir 的函数，例如 symlink()、popen() 等。
使用安全的代码审计工具 | 定期进行代码审计，发现潜在的安全漏洞。
使用 Web 应用防火墙 (WAF) | WAF 可以检测和阻止恶意请求，包括尝试绕过 Open_basedir 的请求。
使用 chroot 环境 | 将 PHP 运行在 chroot 环境中，可以进一步限制文件系统的访问范围。

总结：缓存机制与安全意识

今天我们深入探讨了利用 chdir() 和 realpath() 的缓存特性绕过 Open_basedir 的技术。理解这种绕过方式的关键在于理解 realpath() 的缓存机制以及相对路径的解析过程。同时，我们也讨论了一些防御措施，可以帮助我们提高 PHP 环境的安全性。 只有不断学习和提升安全意识，才能更好地保护我们的 Web 应用程序免受攻击。