WEB常见漏洞之文件上传(靶场篇)1

本文涉及的产品
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
简介: WEB常见漏洞之文件上传(靶场篇)

0x01漏洞概述

upload-labs是一个使用php语言编写的,专门收集渗透测试和CTF中遇到的各种上传漏洞的靶场。旨在帮助大家对上传漏洞有一个全面的了解。目前一共21关,每一关都包含着不同上传方式。

0x02环境配置

在 Windows 下使用 phpstudy 搭建靶场环境,将靶场放置到其 web 环境当中


靶场地址:https://github.com/c0ny1/upload-labs

成功访问说明靶场已经部署完成

思维导图如下:

0x03前端验证

Pass-01

场景分析

直接上传PHP文件浏览器会提示文件类型不正确,这多半就是前端校验

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;
    }
}

从上可知 JS 中定义白名单,白名单里包含.jpg、.png、.gif。前端验证绕过有三个思路,一是满足 JavaScript 规定的条件,通过抓包修改文件名;二是让用于验证的 JavaScript 代码不生效;三是修改 JavaScript 满足上传条件。

抓包绕过

首先将文件名phpinfo.php后缀修改为.png


mv phpinfo.php phpinfo.png

截取上传数据包并后缀名修改为php

成功访问phpinfo.php

禁用JS

使用浏览器插件Quick Javascript Switcher禁用JavaScript

成功访问phpinfo.php

调试JS

在浏览器中选择审查元素并在以下位置中设置断点

创建top/172.16.117.135/upload/Pass-01/index.php目录文件并在其中添加后缀名


var allow_ext = ".jpg|.png|.gif|.php";

在Sources中找到Overrides选择本地目录进行覆盖并保存

刷新网站后再次上传即可直接上传成功

删除JS

复制站点源代码为test.html并从中删除 JavaScript 限制代码

在上传点修改action路径,指定图片上传脚本



<form action="http://172.16.117.135/upload/Pass-01/index.php" enctype="multipart/form-data" method="post" onsubmit="return checkFile()">

选择文件点击上传

成功访问上传文件

0x04后端验证

Pass-02

场景分析

MIME 是什么呢?

MIME(媒体类型)是一种标准,主要用来表示文档、文件或字节流的性质和格式。它的组成结构非常简单,由类型与子类型两个字符串中间用'/'分隔而组成。不允许空格存在。type 表示可以被分多个子类的独立类别。subtype 表示细分后的每个类型。


type/subtype

常见的 MIME 类型包含如下:

application/octet-stream #应用程序的默认值
text/plain #文本类型的默认值
text/html #html类型的默认值
text/css #CSS类型默认值
text/javascript #JavaScript类型的默认值
image/png #png图片的默认值
$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.'文件夹不存在,请手工创建!';
    }
}

这是一个后端校验的 PHP 代码,从上可知其中定义了 MIME 白名单,白名单里包含了image/jpeg、image/png、image/gif,脚本会检测上传数据包的 MIME 类型是否在白名单当中,如果不在白名单之内则无法上传。通过修改上传数据包的 MIME 类型可绕过限制,文件后缀名并没有因此发生改变,我们能直接访问木马文件。

修改MIME

上传php 文件后截取数据包将Content-Type类型修改为图片类型image/png

成功访问上传文件

Pass-03

场景分析

$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
    if (file_exists(UPLOAD_PATH)) {
        $deny_ext = array('.asp','.aspx','.php','.jsp');
        $file_name = trim($_FILES['upload_file']['name']);
        $file_name = deldot($file_name);//删除文件名末尾的点
        $file_ext = strrchr($file_name, '.');
        $file_ext = strtolower($file_ext); //转换为小写
        $file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
        $file_ext = trim($file_ext); //收尾去空
        if(!in_array($file_ext, $deny_ext)) {
            $temp_file = $_FILES['upload_file']['tmp_name'];
            $img_path = UPLOAD_PATH.'/'.date("YmdHis").rand(1000,9999).$file_ext;            
            if (move_uploaded_file($temp_file,$img_path)) {
                 $is_upload = true;
            } else {
                $msg = '上传出错!';
            }
        } else {
            $msg = '不允许上传.asp,.aspx,.php,.jsp后缀文件!';
        }
    } else {
        $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
    }
}

这是一个后端校验的 PHP 代码,从上可知其中定义了文件后缀名黑名单,黑名单里包含.asp、.aspx、.php、.jsp,脚本会检测后缀名是否在黑名单当中,如果在黑名单则无法上传。虽然在黑名单中禁止了典型的脚本后缀名,但是与典型的脚本后缀同义的后缀名还有许多,比如php5、pht、phtml、php4等后缀名都能解析为php脚本,而cer、asa、cdx等后缀名都能解析为asp脚本。因此通过修改同义后缀名可绕过限制。

需要注意的是在默认情况下 php 的同义后缀名是无法解析的。

修改同义后缀名

上传 php 文件后截取数据包将后缀名类型修改为php5

在默认情况下.php5无法被正常解析

解决方法是修改 Apache 默认配置文件httpd.conf并重启


AddType application/x-httpd-php .php .phtml .php5


AllowOverride All

成功访问上传文件

Pass-04

场景分析

$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
    if (file_exists(UPLOAD_PATH)) {
        $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",".ini");
        $file_name = trim($_FILES['upload_file']['name']);
        $file_name = deldot($file_name);//删除文件名末尾的点
        $file_ext = strrchr($file_name, '.');
        $file_ext = strtolower($file_ext); //转换为小写
        $file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
        $file_ext = trim($file_ext); //收尾去空
        if (!in_array($file_ext, $deny_ext)) {
            $temp_file = $_FILES['upload_file']['tmp_name'];
            $img_path = UPLOAD_PATH.'/'.$file_name;
            if (move_uploaded_file($temp_file, $img_path)) {
                $is_upload = true;
            } else {
                $msg = '上传出错!';
            }
        } else {
            $msg = '此文件不允许上传!';
        }
    } else {
        $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
    }
}

这是一个后端校验的 PHP 代码,从上可知其中定义了文件后缀名黑名单,黑名单里几乎包含了所有可解析的后缀名以及.ini,脚本会检测文件后缀名是否在黑名单当中,如果在黑名单当中则无法上传。但黑名单当中忽略了.htaccess文件。


什么是.htaccess呢?

.htaccess文件可用于覆盖 Apache 的默认配置文件httpd.conf修改解析格式来绕过黑名单。它提供了针对目录改变配置的方法,在特定的文档目录中放置该文件可作用此目录以及所有子目录。而.htaccess生效的前提与上一题类似,需要在 Apache 配置文件httpd.conf配置参数AllowOverride为All,因此我们可通过上传定制的.htaccess绕过限制


上传.htaccess

编写.htaccess文件并添加 php 解析,使所有带有 mac 的文件都能解析为 php

    <FilesMatch "mac">
    Sethandler application/x-httpd-php
    </FilesMatch>

    上传时又遇到一个问题:.htaccess无法被选择。我们可将其重命名为1.htaccess后通过 BurpSuite 抓包修改回.htaccess

    然后上传带有 php 代码的mac.png

    成功访问上传文件

    在实战中需要注意的是如果遇到文件名被重命名就不能使用该方法,因为即使重命名为1.htaccess也无法生效,切记

    Pass-05

    场景分析

    访问readme.php并未发现有什么可疑之处

      $is_upload = false;
      $msg = null;
      if (isset($_POST['submit'])) {
          if (file_exists(UPLOAD_PATH)) {
              $deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".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",".htaccess");
              $file_name = trim($_FILES['upload_file']['name']);
              $file_name = deldot($file_name);//删除文件名末尾的点
              $file_ext = strrchr($file_name, '.');
              $file_ext = strtolower($file_ext); //转换为小写
              $file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
              $file_ext = trim($file_ext); //首尾去空
              if (!in_array($file_ext, $deny_ext)) {
                  $temp_file = $_FILES['upload_file']['tmp_name'];
                  $img_path = UPLOAD_PATH.'/'.$file_name;
                  if (move_uploaded_file($temp_file, $img_path)) {
                      $is_upload = true;
                  } else {
                      $msg = '上传出错!';
                  }
              } else {
                  $msg = '此文件类型不允许上传!';
              }
          } else {
              $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
          }
      }

      这是一个后端校验的 PHP 代码,从上可知其中定义了文件后缀名黑名单,黑名单里几乎包含了所有可解析的后缀名和.htaccess,脚本会检测文件后缀名是否在黑名单当中,如果在黑名单当中则无法上传。但黑名单当中忽略了.user.ini文件。


      什么是.user.ini呢?

      .user.ini是 php 中一种配置文件,众所周知当服务器以fastcgi运行脚本程序 php 时,php.ini是 php 的配置文件,它能对文件解析、导入扩展等进行个性化配置,而.user.ini与php.ini类似,它相当于一个用户自定义的php.ini,但不能修改任意php.ini中的属性值,php.ini的属性设置可分为四大类

      PHP_INI_USER #可在用户脚本(如ini_set())、Windows 注册表(PHP 5.3及以上)、.user.ini中设置
      PHP_INI_PERDIR #可在php.ini、.htaccess、httpd.conf中设置
      PHP_INI_SYSTEM #可在php.ini、httpd.conf中设置
      PHP_INI_ALL #可在任何地方设置

      从以上分类可知,只要不是PHP_INI_SYSTEM模式下的属性,均可在.user.ini中设置。auto_append_file以及auto_prepend_file均能自动包含文件且属于PHP_INI_PERDIR模式,通过利用这两个属性可上传.user.ini加载文件可完成文件包含。因此我们可通过上传定制的.user.ini绕过限制

      上传.user.ini

      编写.user.ini文件并添加 php 解析,使名为 mac.gif 的文件解析为 php


      auto_prepend_file=mac.gif

      将.user.ini重命名为1.user.ini后选择上传,通过 BurpSuite 抓包修改文件名回.user.ini

      上传带有 php 代码的mac.gif,这时所有的 php 文件都会包含该图片

      访问readme.php即可完成 php 解析

      目录
      相关文章
      |
      16天前
      |
      安全 关系型数据库 MySQL
      Web安全-条件竞争漏洞
      Web安全-条件竞争漏洞
      27 0
      |
      12天前
      |
      缓存 移动开发 安全
      Web安全-HTTP响应拆分(CRLF注入)漏洞
      Web安全-HTTP响应拆分(CRLF注入)漏洞
      49 8
      |
      12天前
      |
      安全 关系型数据库 Shell
      Web安全-浅析CSV注入漏洞的原理及利用
      Web安全-浅析CSV注入漏洞的原理及利用
      18 3
      |
      14天前
      |
      安全 应用服务中间件 开发工具
      Web安全-SVN信息泄露漏洞分析
      Web安全-SVN信息泄露漏洞分析
      50 2
      |
      16天前
      |
      JSON 安全 JavaScript
      Web安全-JQuery框架XSS漏洞浅析
      Web安全-JQuery框架XSS漏洞浅析
      95 2
      |
      18天前
      |
      安全 搜索推荐 应用服务中间件
      Web安全-目录遍历漏洞
      Web安全-目录遍历漏洞
      20 2
      |
      18天前
      |
      XML JSON 安全
      Web安全-XXE漏洞
      Web安全-XXE漏洞
      14 1
      |
      1月前
      |
      数据库 开发者 Python
      web应用开发
      【9月更文挑战第1天】web应用开发
      41 1
      |
      28天前
      |
      数据可视化 图形学 UED
      只需四步,轻松开发三维模型Web应用
      为了让用户更方便地应用三维模型,阿里云DataV提供了一套完整的三维模型Web模型开发方案,包括三维模型托管、应用开发、交互开发、应用分发等完整功能。只需69.3元/年,就能体验三维模型Web应用开发功能!
      60 8
      只需四步,轻松开发三维模型Web应用
      |
      18天前
      |
      安全 API 开发者
      Web 开发新风尚!Python RESTful API 设计与实现,让你的接口更懂开发者心!
      在当前的Web开发中,Python因能构建高效简洁的RESTful API而备受青睐,大大提升了开发效率和用户体验。本文将介绍RESTful API的基本原则及其在Python中的实现方法。以Flask为例,演示了如何通过不同的HTTP方法(如GET、POST、PUT、DELETE)来创建、读取、更新和删除用户信息。此示例还包括了基本的路由设置及操作,为开发者提供了清晰的API交互指南。
      72 6