专栏首页信安之路目录穿越漏洞修复之后再利用

目录穿越漏洞修复之后再利用

前段时间看到安全狗海青实验室发的一篇关于压缩文件解压导致 getshell 的文章。其中一个漏洞是在 zzzcms1.73 版本。而这款 CMS 自己也算是审过几次,虽然小众,但的确是学习审计的好例子~

安全狗的文章中介绍了 zzzcms 的后台由于上传时存在目录穿越,可以上传到任意路径下,再配合后台解压的功能,就完成了 webshell 的植入。有意思的是,上传功能做了相对严格的后缀检测,而解压功能也只能解压指定文件夹里的压缩包文件,两个功能其实各自都不存在什么大问题,而却因为目录穿越问题导致两个功能点串联在一起,从而完成了 getshell。具体细节可以去看看原文《文件解压引发的 getshell》

目录穿越的助攻

在 zzzcms 的官网上看到做了更新,并且修补了上面提到的漏洞。

下载了最新版的源码,试图绕过修补。然鹅,在尝试数次后,无果。于是,转而看看其他代码。因为之前出现过目录穿越的问题,那么很可能在其他也存在相同的问题。简单翻阅以后,看到如下代码。

很显然,在 69 行我们可以控制一个变量,而这个变量参与了一个路径的构造,因此我们可以控制这个路径跳转到任意目录。而在 78 行处调用了 simplexml_load_file 进行解析 XML,而并没有禁用引用外部实体,所以如果控制了 plug.xml 里的内容,就可以造成一个 XXE 漏洞。

为了控制 plug.xml 文件的内容,需要找到上传功能处。有意思的是,尽管上传功能的目录穿越已经被修补了无法利用,但是这里却存在目录穿越的问题,所以只要上传一个 plug.xml 文件,再控制解析 XML 文件的路径即可完成 XXE。而大多数的上传文件功能都会把文件进行重命名,找到上传功能的代码,如下:

function upload( $file, $type, $folder, $format = NULL, $max_width = NULL, $max_height = NULL ) {
  if ( isset( $file ) ) {
    $files = $file;
  } elseif ( !isset( $_FILES[ $file ] ) ) {
      $files = $_FILES[ $file ];
    } else {
      return array();
    }
    // 定义允许上传的扩展
  if ( !isset( $type ) ) {
    return array( 'state' => '上传类型不能为空' );
  } else {
    switch ( $type ) {
      case 'file':
        $array_ext_allow = explode( ',', Conf( 'fileext' ) );
        $format = Conf( 'fileformat' );
        break;
      case 'video':
        $array_ext_allow = explode( ',', Conf( 'videoext' ) );
        $format = Conf( 'videoformat' );
        break;
      case 'image':
        $array_ext_allow = explode( ',', Conf( 'imageext' ) );
        $format = Conf( 'imageformat' );
        break;
      default:
        $array_ext_allow = explode( ',', strtolower( $type ) );
        break;
    }
  }
  if ( !$files[ 'error' ] ) {
    $upfile = $files[ 'name' ];
    $file_arr = explode( '.', $upfile );
    $file_ext = safe_word(strtolower( end( $file_arr )),'4');        
    $file_name = str_replace( '.' . end( $file_arr ), '', $upfile );
        if(empty($file_ext)) {
            return array( 'state' => '上传类型不能为空!' );
        }elseif ( in_array( $file_ext, array('php','asp','aspx','exe','sh','sql','bat') ) ) {
      return array( 'state' => $file_ext.'格式的文件不允许上传,请重新选择!' );
    } elseif ( !in_array( $file_ext, $array_ext_allow ) ) {
      var_dump($file_ext);
      return array( 'state' => $file_ext . '格式的文件不能上传,请重新选择!');
    }
    $savefile = array( 'state' => 'SUCCESS', 'ext' => $file_ext, 'title' => $file_name, 'url' => handle_upload( $files[ 'name' ], $files[ 'tmp_name' ], $array_ext_allow, $folder, $format, $file_name, $file_ext, $max_width, $max_height ) );
    return $savefile;
  } else {
    return $files[ 'error' ];
  }
}

上面的 代码看到用黑名单限制了后缀名,显然这个黑名单是不严格的,随意上传 php5 这类后缀。检查完后缀之后就来到了 handle_upload 函数,这个函数的主要功能就是将文件进行保存。代码如下:

function handle_upload( $file, $temp, $array_ext_allow, $folder, $format, $file_name, $file_ext, $max_width, $max_height ) {
  // 检查文件存储路径
  if ( conf( 'datefolder' ) == 1 ) {
    $save_path = SITE_DIR . conf( 'uploadpath' ) . $folder . '/' . date( 'Ymd' );
    check_dir( $save_path, true );
  } else {
    $save_path = SITE_DIR . conf( 'uploadpath' ) . $folder;
    check_dir( $save_path, true );
  }
  if ( $format == 'pinyin' ) {
    $newname = pinyin( $file_name );
  } elseif ( $format == 'yuanming' ) {
    $newname = toutf( $file_name );
  } else {
    $newname = time() . mt_rand( 100000, 999999 );
  }
  $file_path = $save_path . '/' . $newname . '.' . $file_ext;
  if ( is_file( $file_path ) ) {
    if ( conf( 'covermark' ) == 1 ) {
      del_file( $file_path );
    } else {
      $file_path = $save_path . '/' . $newname . mt_rand( 1000, 9999 ) . '.' . $file_ext;
    }
  }
  move_uploaded_file( $temp, $file_path ); // 从缓存中转存  
  $save_file = str_replace( SITE_DIR, SITE_PATH, $file_path );
  if ( $format == 'yuanming' )$save_file = togbk( $save_file );
  // 如果是图片进行等比例缩放
  if ( is_image( $file_path )) {
    resize_img( $file_path, $file_path, 0, Conf( 'compresswidth' ), Conf( 'compressheight' ),Conf( 'compressquality') );
  }
  return $save_file;
}

文件名是否随机取决于变量 $format,当 $format 的值为 pinyin 时,则就保存为原文件名。因此,已经可以通过上传一个 plug.xml 来控制 XML 解析的内容。

利用

为了方便验证漏洞,在 C 盘下建立一个目标文件,内容如下。

利用漏洞:

首先先准备一个 plug.xml 文件用于上传。

然后准备一个 a.dtd 文件,放在可控服务器的 web 目录下,

然后编写一个上传页面,

将文件上传

然后触发 XXE 漏洞

POST:

http://127.0.0.1/zzzphp/admin/save.php?act=plugkey
plugpath=../upload/file&plugkey=e10adc3949ba59abbe56e057f20f883e

查看 web 日志,可以发现 flag.txt 的内容被携带的传送到了服务器上。

最后

目录穿越其实只是个小问题,有种打辅助的感觉。就像这个漏洞,如果禁用了外部实体,同样也不能进行 XXE,不过也正是因为目录穿越,这个 XXE 才可以被利用。一直以来分享的文章都很基础很简单,充其量只是个入门的水平,让各位大佬见笑了。:)

本文分享自微信公众号 - 信安之路(xazlsec)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-11-18

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 小白也能看懂的Pandas实操演示教程(上)

    pandas中有两类非常重要的数据结构,就是序列Series和数据框DataFrame.Series类似于NumPy中的一维数组,可以使用一维数组的可用函数和方...

    小小詹同学
  • 想学数据分析但不会Python,过来看看SQL吧(下)~

    之前学到的筛选操作都是基于整个表去进行的,那如果想要依据某列中的不同类别(比如说不同品牌/不同性别等等)进行分类统计时,就要用到数据分组,在SQL中数据分组是使...

    小小詹同学
  • 围观~山东省的小学生Python编程入门都学的什么?

    上午刷微博,又看到关于编程从娃娃抓起的梗,就想起之前看到的新闻,教育部从今年开始将在中小学推广编程教育。

    统计学家
  • 分享|C# 中yield关键字解析

      前段时间了解到yield关键字,一直觉得还不错。今天给大家分享一下yield关键字的用法。yield return 返回集合不是一次性返回所有集合元素,而是...

    Vaccae
  • NVIDIA工程师小姐姐的Python隐藏技巧合集,推特2400赞,代码可以直接跑

    常常发资源的英伟达工程师小姐姐Chip Huyen,又发射了一套Python隐藏功能合集。

    统计学家
  • Jupyter Notebook 使用手册

    什么是“笔记本(notebook)”?记事本将代码及其输出集成到一个文档中,该文档结合了可视化、叙述性文本、数学方程和其他富媒体。这种直观的工作流程促进了迭代和...

    HuangWeiAI
  • 神器与神器:微软宣布VsCode支持Jupyter Notebook

    大家都知道Jupyter Notebook是一款编写Python的神器,然而编辑Jupyter Notebook离不开网页,很多本地的编辑器都不支持编译Note...

    HuangWeiAI
  • Java 会走向晦暗吗? Kotlin 会取而代之吗

    Stackoverflows上的趋势图显示Java从2015年以后走下坡路,而Kotlin开始上升。该图形中的Java趋势不断下降,Java很容易失去其作为一种...

    良月柒
  • 干货 | 27 个问题,告诉你 Python 为什么如此设计?

    https://docs.python.org/zh-cn/3.7/faq/design.html

    统计学家
  • Python进阶之Matplotlib入门(五)

    Matplotlib是Python的画图领域使用最广泛的绘图库,它能让使用者很轻松地将数据图形化以及利用它可以画出许多高质量的图像,是用Python画图的必备技...

    HuangWeiAI

扫码关注云+社区

领取腾讯云代金券