Web渗透:文件上传-后端过滤

news2025/1/15 17:43:06

在上一篇文件上传的内容中笔者阐述了文件上传漏洞产生的相关原理以及使用了一个pikachu靶场的例子进行演示,在这个例子中涉及到了前端代码对于文件上传漏洞的相关防护,以及站在攻击者的角度我们要如何绕过前端的防护成功进行攻击;但是事实上对于文件上传漏洞相关的安全防护不仅在前端能够部署,在后端也能够部署,那么本文我们就来探讨一下在后端的相关过滤措施有哪些以及站在攻击者的角度我们如何进行绕过。

1.MIME类型过滤:

MIME:

MIME(Multipurpose Internet Mail Extensions)是一种互联网标准,用于描述电子邮件、Web等互联网应用中传输的数据类型。MIME类型最初是为了解决电子邮件中传输多媒体内容的问题,现在已经广泛用于HTTP协议中,用于描述和处理多种类型的网络资源。

MIME类型的结构

MIME类型由两部分组成,格式为type/subtype

  • type:主要类型,表示数据的大类,例如textimageaudiovideoapplication等。

  • subtype:具体子类型,表示数据的具体格式,例如plainhtmljpegpngmpegjson等。

例如:

text/html 表示HTML文档
image/jpeg 表示JPEG图像
application/json 表示JSON数据

言归正传,文件上传MIME类型过滤是指在文件上传功能中,通过检查上传文件的MIME类型来限制允许上传的文件类型。这可以防止用户上传恶意文件,增强应用程序的安全性。以下是一些关于如何实现文件上传MIME类型过滤的详细信息和示例。

相关源码:

<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $allowedTypes = ['image/jpeg', 'image/png', 'application/pdf'];
    $fileType = mime_content_type($_FILES['file']['tmp_name']);
​
    if (!in_array($fileType, $allowedTypes)) {
        die('Invalid file type.');
    }
​
    // 处理文件上传逻辑,例如移动文件到目标目录
    move_uploaded_file($_FILES['file']['tmp_name'], 'uploads/' . basename($_FILES['file']['name']));
    echo 'File uploaded successfully.';
}
?>
<form method="POST" enctype="multipart/form-data">
  <input type="file" name="file">
  <button type="submit">Upload</button>
</form>
 

$allowedTypes = ['image/jpeg', 'image/png', 'application/pdf'];定义一个数组,包含允许上传的文件MIME类型。

$fileType = mime_content_type($_FILES['file']['tmp_name']);使用mime_content_type函数获取上传文件的MIME类型。$_FILES['file']['tmp_name']是上传文件的临时文件路径。

if (!in_array($fileType, $allowedTypes)) {
    die('Invalid file type.');
}
  • 使用in_array函数检查上传文件的MIME类型是否在允许的类型列表中。如果不在,则终止脚本执行并输出"Invalid file type."。

绕过方式:

通过BP抓包,通过修改请求头中的Content-Type字段进行绕过;当我们上传的文件为php文件时,该字段的内容如下图:

这个时候我们可以将该字段修改为如下示例MIME类型进行绕过:

image/jpeg, image/png, application/pdf,text/plain,text/html,image/png

以下是一个包含常见MIME类型的表格(10行):

文件扩展名MIME类型描述
.htmltext/htmlHTML文档
.csstext/cssCSS样式表
.jstext/javascriptJavaScript代码
.jsonapplication/jsonJSON格式
.jpgimage/jpegJPEG图像
.pngimage/pngPNG图像
.gifimage/gifGIF图像
.mp3audio/mpegMP3音频
.mp4video/mp4MP4视频
.pdfapplication/pdfPDF文档

当然可修改的值不止这些,我们完全可以将各种MIME类型存入txt文件中,到时候再使用BP进行FUZZ测试即可。

2.扩展名验证:

①黑名单:

使用扩展名黑名单是防止文件上传漏洞的一种有效方法。通过禁止上传包含特定扩展名的文件,可以减少恶意文件被上传到服务器的风险。以下是一些常见的恶意文件扩展名,可以添加到黑名单中;相关代码(upload靶场为例):

 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后缀文件!';
        }
代码逻辑:

$deny_ext = array('.asp','.aspx','.php','.jsp');定义一个数组,包含不允许上传的文件扩展名。

接着通过对上传文件名进行处理,获取上传文件的扩展名;紧接着!in_array($file_ext, $deny_ext)判断当前上传文件扩展名是否再黑名单列表中,若在则禁止上传(不将文件进行保存)。

此时的绕过思路:

使用特殊文件后缀进行绕过,以php为例子:

①.php3, .php4, .php5, .php7:用于指定 PHP 版本的文件后缀,较少使用。
②.phtml:表示包含 PHP 代码的 HTML 文件,通常用于混合 HTML 和 PHP 代码。
③.inc:通常表示包含文件(include file),虽然本身不是 PHP 后缀,但常包含 PHP 代码并通过 include 或 require 引入其他 PHP 文件。(需要配合文件包含漏洞)

因为上述代码中的黑名单列表并不完善所以这个时候我们只需要将php文件后缀进行修改上传即可。如果是自身在进行开发时需要将黑名单列表尽可能地完善,一下时常见的黑名单列表:

.php, .php3, .php4, .php5, .phtml, .phps, .asp, .aspx, .jsp, .jspx, .cfm, .cgi, .pl, .py, .rb, .sh, .bat, .exe, .com, .cmd, .dll, .scr, .msi, .vbs, .js, .jse, .wsf, .wsh, .ps1

②白名单

在文件上传防护中,使用白名单过滤是一个有效的方法,通过只允许特定的、安全的文件类型和扩展名来降低风险。以下是如何实现白名单过滤的详细步骤及示例代码:

if(isset($_POST['submit'])){
    $ext_arr = array('jpg','png','gif');
    $file_ext = substr($_FILES['upload_file']['name'],strrpos($_FILES['upload_file']['name'],".")+1);
    if(in_array($file_ext,$ext_arr)){
        $temp_file = $_FILES['upload_file']['tmp_name'];
        $img_path = $_GET['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;
​
        if(move_uploaded_file($temp_file,$img_path)){
            $is_upload = true;
        } else {
            $msg = '上传出错!';
        }
    } else{
        $msg = "只允许上传.jpg|.png|.gif类型文件!";
    }
}
?>

$ext_arr = array('jpg','png','gif');设置了允许上传文件后缀的白名单列表;当文件后缀名在白名单中才能够成功上传文件。

绕过方式:

00截断:当文件名中包含NULL字符时,某些编程语言和服务器会在处理字符串时将NULL字符后的内容截断。例如,在PHP中,example.php\0.jpg文件名在某些情况下会被截断为example.php,从而绕过扩展名检查。

其他绕过手法总结
1.大小写绕过:利用服务器文件系统或代码对文件扩展名大小写不敏感的特性,绕过安全检测和过滤。

一些文件系统不区分文件名的大小写,这意味着 example.phpexample.PHP 被视为同一个文件。在这种情况下,攻击者可以使用大小写变种绕过文件扩展名的检测。

Windows 文件系统(NTFS、FAT32):默认情况下不区分大小写。
macOS 文件系统(HFS+):默认情况下不区分大小写。
Linux 文件系统(ext3、ext4、XFS):默认情况下区分大小写。

但是在上述代码中包含将获取的扩展名进行统一转换的操作:

$file_ext = strtolower($file_ext); //转换为小写

所以此时大小写绕过放在上一个环境中无法生效。

2.双重扩展名

通过使用双重扩展名,服务器可能只检查第一个扩展名,从而绕过检测。

示例:

  • example.php.aa

  • example.php.bb

此时中间件在进行解析时会从后往前进行识别,将自身能够辨别的后缀名作为当前文件的类型。

3.文件内容混淆

原理:在文件内容中添加无害字符或注释,使其通过内容检查。

示例:

在PHP文件中添加JPEG文件头。

适用条件:服务器检查文件内容,但允许无害字符。

4.特殊字符绕过

原理:利用特殊字符或编码方式绕过检查。

示例:example.php%00.jpg(%00 是 NULL 字符)

适用条件:服务器在处理字符串时忽略特殊字符或编码。

5.编码绕过

原理:通过URL编码或Unicode编码绕过检查。

示例:example%2Ephp(%2E 代表 .)

适用条件:服务器在处理编码时不进行解码或不正确解码。

6.::$DATA

原理:利用NTFS文件系统的ADS特性,在文件名中加入::$DATA

示例:example.php::$DATA

适用条件:服务器运行在Windows且使用NTFS文件系统。

防御措施

1.严格的白名单机制:只允许特定的文件扩展名和MIME类型。
2.统一转换为小写:在处理扩展名时,统一将其转换为小写。
3。验证文件内容:不仅检查文件扩展名,还要检查文件内容的实际类型(MIME类型和文件头)。
4.移除特殊字符:在处理文件名时,移除包括NULL字符和::等特殊字符。
5.重命名上传文件:上传文件后,重命名文件以移除任何潜在的恶意扩展名。
6.设置正确的文件权限:确保上传目录没有执行权限,防止文件被执行。
示例代码

以下是一个综合了多种防御措施的文件上传代码示例:

<?php
function sanitize_filename($filename) {
    // 移除NULL字符和NTFS数据流标识符以及其他特殊字符
    $filename = str_replace(["\0", '::$DATA'], '', $filename);  
    $filename = preg_replace('/[^a-zA-Z0-9._-]/', '', $filename);
    return $filename;
}
​
$allowed_ext = array('jpg', 'jpeg', 'png', 'pdf');  //后缀名白名单
$allowed_mime_types = array('image/jpeg', 'image/png', 'application/pdf'); //mime白名单
​
$file_name = sanitize_filename($_FILES['upload_file']['name']);
$file_ext = strtolower(pathinfo($file_name, PATHINFO_EXTENSION));
​
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$file_mime_type = finfo_file($finfo, $_FILES['upload_file']['tmp_name']);
finfo_close($finfo);
​
if (in_array($file_ext, $allowed_ext) && in_array($file_mime_type, $allowed_mime_types)) {
    $temp_file = $_FILES['upload_file']['tmp_name'];
    $destination = 'uploads/' . uniqid() . '.' . $file_ext;
    if (move_uploaded_file($temp_file, $destination)) {
        echo 'File uploaded successfully.';
    } else {
        echo 'Error moving uploaded file.';
    }
} else {
    echo 'Invalid file type.';
}
?>
​
<form method="POST" enctype="multipart/form-data">
  <input type="file" name="upload_file">
  <button type="submit">Upload</button>
</form>
 

安全性分析

  1. 文件名清理sanitize_filename函数移除NULL字符和NTFS数据流标识符,并只保留字母、数字、点、下划线和横杠。这有效地防止了常见的文件名绕过技术。

  2. 文件扩展名和MIME类型检查

    ①检查文件扩展名是否在允许的列表中。

    ②使用finfo_file函数获取文件的MIME类型,并检查它是否在允许的列表中。这双重检查确保文件类型是安全的。

  3. 唯一文件名:使用uniqid函数生成唯一文件名,避免文件覆盖问题。

  4. 错误处理:如果文件移动失败,输出错误信息;这虽然不能完全防止攻击,但可以帮助调试和改进代码。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1853853.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

每日签到页面模板组件,简单好用,用了会上瘾的那种

uni-app 是一个使用 Vue.js 开发所有前端应用的框架&#xff0c;开发者编写一套代码&#xff0c;可发布到iOS、Android、Web&#xff08;响应式&#xff09;、以及各种小程序&#xff08;微信/支付宝/百度/头条/飞书/QQ/快手/钉钉/淘宝&#xff09;、快应用等多个平台。 今日给…

Django之云存储(二)

一、Django使用云存储 建立项目 django-admin startproject project_demo创建子应用 python manage.py startapp app_name修改配置文件,设置模板视图路径 settings.py TEMPLATES = [{BACKEND: django.template.backends.django.DjangoTemplates,DIRS: [os.path.join(BASE_DIR,…

【Unity服务器01】之AssetBundle上传加载u3d模型

首先打开一个项目导入一个简单的场景 导入怪物资源&#xff0c; AssetBundle知识点&#xff1a; 1.指定资源的AssetBundle属性标签 &#xff08;1&#xff09;找到AssetBundle属性标签 &#xff08;2&#xff09;A标签 代表&#xff1a;资源目录&#xff08;决定打包之后在哪…

微信小程序之横向列表展示

效果图 参考微信小程序可看 代码&#xff1a; <view class"lbtClass"><view class"swiper-container"><scroll-view class"swiper" scroll-x"true" :scroll-left"scrollLeft"><block v-for"(six…

怎么用Excel生成标签打印模板,自动生成二维码

环境&#xff1a; EXCEL2021 16.0 问题描述&#xff1a; 怎么用excel生成标签打印模板自动生成二维码 解决方案&#xff1a; 在Excel中生成标签打印模板并自动生成二维码&#xff0c;可以通过以下几个步骤完成&#xff1a; 1. 准备数据 首先&#xff0c;确保你的Excel表…

C#.net6.0+sqlserver2019医院手术麻醉信息管理系统源码 可对接院内HIS、LIS、PACS 支持二次开发

C#.net6.0sqlserver2019医院手术麻醉信息管理系统源码 可对接院内HIS、LIS、PACS 支持二次开发 手麻系统的功能涵盖了麻醉临床业务管理、麻醉运营业务管理以及手术进程管理等&#xff0c;实现了将多种麻醉病历文书与医院HIS系统的有效关联&#xff0c;让手术室人员、设备资源和…

鹅算法(GOOSE Algorithm,GOOSE)求解复杂城市地形下无人机避障三维航迹规划,可以修改障碍物及起始点(Matlab代码)

一、鹅算法 鹅优化算法&#xff08;GOOSE Algorithm&#xff0c;GOOSE)从鹅的休息和觅食行为获得灵感&#xff0c;当鹅听到任何奇怪的声音或动作时&#xff0c;它们会发出响亮的声音来唤醒群中的个体&#xff0c;并保证它们的安全。 参考文献 [1]Hamad R K, Rashid T A. GOO…

day16--513.找树左下角的值+112. 路径总和+106.从中序与后序遍历序列构造二叉树

一、513.找树左下角的值 题目链接&#xff1a;https://leetcode.cn/problems/find-bottom-left-tree-value/ 文章讲解&#xff1a;https://programmercarl.com/0513.%E6%89%BE%E6%A0%91%E5%B7%A6%E4%B8%8B%E8%A7%92%E7%9A%84%E5%80%BC.html 视频讲解&#xff1a;https://www.b…

JavaSE基础总结复习之面向对象の知识总结

目录 Java语言的基础特点 面向对象 类和对象 类 类的构造 一&#xff0c;发现类 二&#xff0c;发现类的共有属性&#xff08;成员变量&#xff09; 三&#xff0c;定义类的成员方法&#xff08;行为&#xff0c;动词&#xff09; 四&#xff0c;使用类创建对象 对象…

Linux——man帮助命令

一、man 获得帮助信息 基本语法&#xff1a;man [命令或配置文件] &#xff08;功能描述&#xff1a;获得帮助信息&#xff09; 查看 ls 命令的帮助信息 [roothadoop101 ~]# man ls man [数字] [函数] 1、Standard commands &#xff08;标准命令&#xff09; 2、System…

Structured Steaming结构化流详解:大案例解析(第12天)

系列文章目录 一、结构化流介绍&#xff08;了解&#xff09; 二、结构化流的编程模型&#xff08;掌握&#xff09; 三、Spark 和 Kafka 整合&#xff0c;流处理&#xff0c;批处理演示&#xff08;掌握&#xff09; 四、物联网数据分析案例&#xff08;熟悉&#xff09; 文章…

【服务器06】之【如何不开外网连接GitHub】

登录GitHub官网 GitHub: Let’s build from here GitHub 注册账号 登录账号 输入一个自定义名字&#xff0c;点击创建存储库就可以了 首先 如何在不开外网的条件下使用GitHub 第一步 下载安装Steam(Watt TooklKit) 区分一下如何查看哪个官网&#xff08;没有百度广告就是…

CPP-类对象大小的组成

要计算一个类对象的大小要先明白一个问题&#xff1a;类中既可以有成员变量&#xff0c;又可以有成员函数&#xff0c;那么一个类的对象中包含了什么&#xff1f; 下面来看一段代码&#xff1a; // 类中既有成员变量&#xff0c;又有成员函数 class A1 { public:void f1() {} …

Pytorch调试出错记录

一、搭建环境&#xff1a; LINUX-64 1、 nvidia-smi &#xff1a;NVIDIA-SMI 470.63.01 Driver Version: 470.63.01 CUDA Version: 11.4 2、安装conda&#xff1a;下载最新版上传安装 3、安装pytorch&#xff08;安装成功&#xff0c;但可能报错&#xff09; : conda in…

AI 大模型应用开发实战(04)-AI生态产业拆解

1 行业全景图 2 结构拆解AI GC 生成式AI这个产业。分成上中下游三大块。 2.1 上游基础层 主要包括&#xff1a; 算力&#xff1a;包括AI芯片和云服务等&#xff0c;例如像英伟达、AMD以及华为等厂商提供的算力基础设施。大型模型基于Transformer架构&#xff0c;对算力的需…

redis主从复制、哨兵、集群

在实际的生活环境中&#xff0c;如果只使用一个redis进行读写操作&#xff0c;那么面对庞大的访问人群是崩溃的&#xff0c;所以可以有几个redis&#xff0c;一个用来做主机&#xff0c;提供修改数据操作&#xff0c;而这个主机用来控制其他redis&#xff0c;即将更新的发送&am…

C/C++ - 编码规范(USNA版)

[IC210] Resources/C Programming Guide and Tips 所有提交的评分作业&#xff08;作业、项目、实验、考试&#xff09;都必须使用本风格指南。本指南的目的不是限制你的编程&#xff0c;而是为你的程序建立统一的风格格式。 * 这将有助于你调试和维护程序。 * 有助于他人&am…

号外!号外!全网第一手Android P刘海屏适配大揭秘,唯一Kotlin算法

如下图所示&#xff1a; 4.2.适配刘海屏 在刘海屏调试打开之后&#xff0c;浏览应用的所有页面&#xff0c;测试所有遮挡问题&#xff0c;或者是下移导致的问题&#xff0c;对有问题的页面进行布局适配。适配方案如下&#xff1a; Google 提供的适配方案&#xff0c;可以设置…

基于Vue-cli脚手架搭建项目使用ElementUI组件

项目结构 node_modules 项目依赖的外部组件文件放在此处,例如vue public index.html是对外提供的唯一的html文件 src assets 存放静态文件 例如图片 css js等文件 components 里面存放的是组件 App.vue是组件 main.js是项目配置文件 package.json存放的是项目依赖的…

1.树莓派4b+ubuntu18.04(ros版本melodic)+arduino mega自制两轮差速小车,实现建图导航功能

第一篇先介绍材料准备、环境配置和ros的安装 1.材料准备 1.树莓派4b&#xff0c;8g版本 2.arduino mega 3.MG310编码电机*2 4.雷达ydlidar X3 5.Tb6612电机驱动板 6.12v电池 7.ubuntu18.04ros melodic版本 2.环境配置 树莓派安装ubuntu18.04版本 ubuntu18.04版本的镜像可以…