上传漏洞攻击总结

文件上传shell是在渗透测试过程中,获得服务器权限最快最直接的方法,只有存在上传漏洞,服务器就岌岌可危。

0x00 文件上传检验的方式

可分为服务端和客户端:

  • JavaScript前端检验(检测文件扩展名)
  • 服务端检验
    • MIME类型检测(content-type 内容)
    • 目录路径检测 (path参数相关的内容)
    • 文件扩展名检测 (文件extension相关的内容)
    • 文件内容检测 (检测内容是否合法或含有恶意代码)
    • 文件头检测
    • 文件加载检测

具体检测的内容如下,通常一个文件以HTTP 协议进行上传时,将以POST 请求发送至web 服务器
web 服务器接收到请求后并同意后,用户与web 服务器将建立连接,并传输data。

0x01 绕过各类检测方式

客户端检测

在网页上写一段JavaScript的检测代码,检测上传的文件是否是合法的后缀。

function checkFile() {
    var file = document.getElementsByName('upload_file')[0].value;
    if (file == null || file == "") {
        alert("请选择要上传的文件!");
        return false;
    }
    //定义允许上传的文件类型
    var allow_ext = ".jpg|.png|.gif";
    //提取上传文件的类型
    var ext_name = file.substring(file.lastIndexOf("."));
    //判断上传文件类型是否允许上传
    if (allow_ext.indexOf(ext_name + "|") == -1) {
        var errMsg = "该文件不允许上传,请上传" + allow_ext + "类型的文件,当前文件类型为:" + ext_name;
        alert(errMsg);
        return false;
    }
}

绕过方式:可以通过burpsuite抓包,进行改filename,也可以通过禁用JS。

服务端检测

1、MIME类型检测绕过

服务器对content-type 的字段进行检测

$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
    if (file_exists(UPLOAD_PATH)) {
        if (($_FILES['upload_file']['type'] == 'image/jpeg') || ($_FILES['upload_file']['type'] == 'image/png') || ($_FILES['upload_file']['type'] == 'image/gif')) {
            $temp_file = $_FILES['upload_file']['tmp_name'];
            $img_path = UPLOAD_PATH . '/' . $_FILES['upload_file']['name']            
            if (move_uploaded_file($temp_file, $img_path)) {
                $is_upload = true;
            } else {
                $msg = '上传出错!';
            }
        } else {
            $msg = '文件类型不正确,请重新上传!';
        }
    } else {
        $msg = UPLOAD_PATH.'文件夹不存在,请手工创建!';
    }
}

从上面的代码可以看出,服务器对上传的文件,content-typeimage/jpeg,image/png,image/gif 才可以通过上传。

我们只需要抓取数据包,将content-type 改为其中一种即可。

1543631829(1)

可以看到当字段content-type: application/octet-stream是上传失败的。改为image/jpg:

1543632004(1)

可以看到已经上传成功了。

2、目录路径检测绕过

目录路径检测,一般就检测路径是否合法,但稍微特殊一点的都没有防御。漏洞成因是因为对目录路径的检测不够严谨而导致可以用0x00 截断进行攻击。

3、文件扩展名检测绕过

文件扩展名检测一般有黑名单和白名单,白名单比黑名单的安全性高,攻击的手法自然就少。

黑名单:

一般的backlist如下:

$deny_ext = array(".php",".php5",".php4",".php3",".php2","php1",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2","pHp1",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf");

绕过方式:

  • 文件名大小写绕过(对于大小写不敏感的Windows)

    Asp,pHp等可以绕过黑名单

  • 名单列表绕过

    用黑名单里没有的名单进行攻击

  • 特殊文件名绕过

    比如发送的http 包里把文件名改成test.asp. 或test.asp_(下划线为空格),然后绕过验证后,会
    被windows 系统自动去掉后面的点和空格,但要注意Unix/Linux 系统没有这个特性。

    test.asp.
    test.asp::$DATA  //利用windows NTFS流
    test.asp(空格)
    test.php:1.jpg
    
  • 0x00 截断绕过

    基于一个组合逻辑漏洞造成的,通常存在于构造上传文件路径的时候

    test.php(0x00).jpg
    test.php%00.jpg
    路径/upload/1.php(0x00),文件名1.jpg,结合/upload/1.php(0x00)/1.jpg
    
  • .htaccess 文件攻击

    无论是黑名单还是白名单再直接点就是直接攻击.htaccess 文件,配合名单列表绕过,上传一个自定义的.htaccess,就可以轻松绕过各种检测

  • 配合解析漏洞和其他编辑器漏洞

    这类漏洞直接配合上传一个代码注入过的非黑名单文件即可,再利用解析调用/漏洞

白名单:

白名单的攻击方式相对少一些。

$ext_arr = array('jpg','png','gif');

绕过方式:

  • 0x00截断
  • 配合解析漏洞和其他编辑器漏洞

4、文件内容检测绕过

文件内容检测分为文件头检测和文件加载检测,文件加载通过调用API重新渲染图片,将图片一些不必要的信息去掉,重新生成图片。

如果文件内容检测设置得比较严格,那么上传攻击将变得非常困难,也可以说它是在代码层检测的最后一道关卡,如果它被突破了,就算没有代码层的漏洞,也给后面利用应用层的解析漏洞带来了机会。

文件头检测:

主要是检测文件开头处的文件幻数。不同的图片文件都有不同文件头,如:

PNG: 文件头标识 (8 bytes) 89 50 4E 47 0D 0A 1A 0A

JPEG: 文件头标识 (2 bytes): 0xff, 0xd8 (SOI) (JPEG 文件标识)

GIF: 文件头标识 (6 bytes) 47 49 46 38 39(37) 61

PHP使用getimagesize函数验证图片文件头,代码示例:

function isImage($filename){
    $types = '.jpeg|.png|.gif';
    if(file_exists($filename)){
        $info = getimagesize($filename);
        $ext = image_type_to_extension($info[2]);
        if(stripos($types,$ext)){
            return $ext;
        }else{
            return false;
        }
    }else{
        return false;
    }
}

文件相关信息的检测:

图像文件信息检测常用就是getimagesize() 函数,就是在幻数的基础上还加了一些文件信息

GIF89a
(...some binary data for image...)
<?php phpinfo(); ?>
(... skipping the rest of binary data ...)

文件加载检测:

最变态的检测,一般是调用API或函数去进行文件加载测试。常见的是图像渲染测试,还有二次渲染(更加变态)什么是二次渲染呢?二次渲染就是调用API,例如php的GD库,重新生成一张图片,在生成的过程中,把原本属于图像数据的部分抓了出来,再用自己的API 或函数进行重新渲染

  • 对渲染/加载测试的攻击方式是代码注入绕过
  • 对二次渲染攻击方式是攻击文件加载器自身

绕过方式:

  1. 渲染/加载测试的攻击方式是代码注入绕过

    在不破坏文件本身的渲染情况下找一个空白区进行代码填充,一般会是图片的注释区,文件结构要完整。

  2. 二次渲染

    参考:https://paper.seebug.org/387/#2-php-gdwebshell

    ​ https://github.com/RickGray/Bypass-PHP-GD-Process-To-RCE

    ​ http://www.secgeek.net/bookfresh-vulnerability/

0x02 上传攻击框架

1、轻量的检测绕过

  • 绕过JavaScript对扩展名的检测
  • 绕过服务端对MIME类型检测

2、路径/扩展名检测绕过

黑名单绕过

  • 文件名大小写(主要windows)
  • 名单列表绕过
  • 特殊文件名绕过
  • 0x00截断绕过
  • .htaccess文件攻击
  • php文件包含漏洞
  • Apache解析漏洞
  • IIS解析漏洞
  • nginx解析漏洞

白名单绕过

  • 0x00截断
  • Apache解析漏洞
  • IIS解析漏洞
  • nginx解析漏洞

3、文件内容检测绕过

  • 文件加载绕过

4、攻击mind图

1543667612(1)

5、攻击的流程

1543641408(1)

0x03 后记

一些平时大家当小技巧对待的东西,以后会成为主要攻击手段之一。