揭秘文件上传漏洞之操作原理(Thoughts on File Upload Vulnerabilities)

从上传到入侵:揭秘文件上传漏洞之操作原理

大家好,今天我们来聊一个"老而弥坚"的漏洞类型 —— 文件上传漏洞。虽然这个漏洞存在很多年了,但直到现在依然频频出现在各种漏洞报告中。今天我们就来深入了解一下它的原理和各种校验方式。

上传过程中到底发生了什么?

说到文件上传,很多人可能觉得不就是选个文件,点击上传按钮吗?但实际上,背后的过程可复杂了。

当你点击那个上传按钮时,浏览器会构造一个特殊的HTTP请求。这个请求会把Content-Type设置为multipart/form-data,这是专门用来传输文件的格式。请求大概长这样:

POST /upload.php HTTP/1.1
Host: example.com
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryABC123
Content-Length: 1136------WebKitFormBoundaryABC123
Content-Disposition: form-data; name="file"; filename="test.jpg"
Content-Type: image/jpeg[文件二进制内容]
------WebKitFormBoundaryABC123--

服务器收到这个请求后,会经历以下步骤:

  1. 解析请求,提取文件内容

  2. 创建临时文件,存储上传的内容

  3. 进行各种校验(这是重点!)

  4. 如果校验通过,将文件移动到目标目录

  5. 返回上传结果

看起来很完整的流程对吧?但问题就出在第三步 —— 校验环节。

为什么会出现上传漏洞?

文件上传漏洞的本质是什么?说白了就是:服务器没有正确验证上传文件的类型,或者验证被绕过了,导致攻击者可以上传恶意文件并执行。

主要的成因有这么几类:

1. 校验位置不当

最典型的就是只在前端做校验。比如这样的代码:

function checkFile(){var file = document.getElementById('upload').files[0];if(file.type != 'image/jpeg'){alert('只能上传jpg图片!');return false;}return true;
}

这种校验形同虚设,因为前端的任何校验都可以被绕过。用户完全可以直接构造POST请求,根本不经过这个JavaScript校验。

2. 校验逻辑不完整

很多开发者的校验逻辑是这样的:

$filename = $_FILES['upload']['name'];
$ext = substr($filename, strrpos($filename, '.'));
if($ext != '.jpg'){die('只允许上传jpg文件!');
}

这种校验存在多个问题:

  • 没有考虑大小写(.JPG, .jpg)

  • 没有考虑多重后缀(test.php.jpg)

  • 没有考虑特殊字符(test.jpg.php%00)

3. 服务器解析漏洞

就算开发者做了完善的后缀名校验,还可能踩到服务器解析的坑。不同的Web服务器对文件解析的规则不同:

  • IIS会把"test.asp;.jpg"当作ASP文件

  • Apache可能会解析"test.php.xxx"为PHP文件

  • Nginx某些版本存在解析漏洞

这就导致即使上传的文件后缀是.jpg,但服务器可能还是会以PHP等方式解析它。

服务器通常会做哪些校验?

说完了问题,我们来看看一个完整的校验流程应该包含哪些内容:

1. MIME类型校验

// 获取文件的真实MIME类型
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime_type = finfo_file($finfo, $_FILES['upload']['tmp_name']);// 白名单验证
$allow_mime = array('image/jpeg', 'image/png', 'image/gif');
if(!in_array($mime_type, $allow_mime)){die('非法文件类型');
}

2. 文件内容校验

// 检查是否真的是图片
if(!getimagesize($_FILES['upload']['tmp_name'])){die('非法图片文件');
}// 检查文件内容是否包含PHP代码
$content = file_get_contents($_FILES['upload']['tmp_name']);
if(preg_match('/<\?php/i', $content)){die('发现PHP代码');
}

3. 文件名和后缀校验

// 提取文件后缀
$ext = strtolower(pathinfo($_FILES['upload']['name'], PATHINFO_EXTENSION));// 白名单检查
$allow_ext = array('jpg', 'jpeg', 'png', 'gif');
if(!in_array($ext, $allow_ext)){die('非法文件类型');
}// 文件名合法性检查
if(!preg_match("/^[a-zA-Z0-9_]+\.[a-zA-Z0-9]+$/", $_FILES['upload']['name'])){die('非法文件名');
}

4. 文件完整性校验

// 检查文件大小
if($_FILES['upload']['size'] > 2*1024*1024){die('文件过大');
}// 检查图片尺寸
list($width, $height) = getimagesize($_FILES['upload']['tmp_name']);
if($width > 1920 || $height > 1080){die('图片尺寸过大');
}

如何做好上传验证?

一个安全的文件上传验证流程应该是这样的:

  1. 文件名合法性验证

  • 去除路径信息

  • 检查特殊字符

  • 验证扩展名白名单

  1. 文件类型验证

  • 检查MIME类型

  • 验证文件头

  • 内容检测

  1. 存储安全

  • 重命名文件

  • 使用随机文件名

  • 限制存储目录

  • 设置合适的权限

  1. 其他措施

  • 限制上传大小

  • 限制上传频率

  • 记录上传日志

  • 杀毒检查

每一步都很重要,缺一不可。而且这些措施要多管齐下,形成纵深防御。

总结

文件上传漏洞说简单也简单,说复杂也复杂。简单在于原理容易理解,复杂在于防护要考虑的点实在太多。怎么样?通过这篇文章,你是不是对文件上传漏洞有了更深的认识?在实际开发中,你还遇到过哪些有趣的文件上传相关的问题呢?欢迎在评论区分享你的经验!

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

网络安全 | 云安全与物联网(IoT)

网络安全 | 云安全与物联网&#xff08;IoT&#xff09; 一、前言二、云计算与物联网概述2.1 云计算2.2 物联网 三、物联网中的云安全需求与挑战3.1 数据安全3.2 网络安全3.3 身份认证与访问控制3.4 设备安全 四、云安全在物联网中的应对策略4.1 技术层面4.2 管理层面 五、案例…

FFmpeg:详细安装教程与环境配置指南

FFmpeg 部署完整教程 在本篇博客中&#xff0c;我们将详细介绍如何下载并安装 FFmpeg&#xff0c;并将其添加到系统的环境变量中&#xff0c;以便在终端或命令行工具中直接调用。无论你是新手还是有一定基础的用户&#xff0c;这篇教程都能帮助你轻松完成 FFmpeg 的部署。 一、…

基于Redis有序集合实现滑动窗口限流

滑动窗口算法是一种基于时间窗口的限流算法&#xff0c;它将时间划分为若干个固定大小的窗口&#xff0c;每个窗口内记录了该时间段内的请求次数。通过动态地滑动窗口&#xff0c;可以动态调整限流的速率&#xff0c;以应对不同的流量变化。 整个限流可以概括为两个主要步骤&a…

C++——deque的了解和使用

目录 引言 标准库中的deque 一、deque的基本概念 二、deque的常用接口 1.deque的迭代器 2.deque的初始化 3.deque的容量操作 3.1 有效长度和容量大小 3.2 有效长度和容量操作 4.deque的访问操作 5.deque的修改操作 三、deque的应用场景 结束语 引言 在C中&#x…

【蓝桥杯】:蓝桥杯之路径之谜

题目分析 这是一道路径谜题&#xff0c;描述了一个骑士在一个(n\times n)方格组成的城堡中行走的问题。骑士从西北角&#xff08;入口&#xff09;走到东南角&#xff08;出口&#xff09;&#xff0c;可以横向或纵向移动&#xff0c;但不能斜着走&#xff0c;也不能跳跃。每走…

Mybatis 入门

Mybatis 入门 一、简介 mybatis 是一个优秀的基于 java 的持久层框架&#xff0c;它内部封装了 jdbc&#xff0c;使开发者只需要关注 sql 语句本身&#xff0c; 而不需要花费精力去处理加载驱动、创建连接、创建 statement 等繁杂的过程。 mybatis 通过 xml 或注解的方式将要…

《Java核心技术 卷II》流的创建

流的创建 Collection接口中stream方法可以将任何集合转换为一个流。 用静态Stream.of转化成数组。 Stream words Stream.of(contents.split("\\PL")); of方法具有可变长参数&#xff0c;可以构建具有任意数量的流。 使用Array.stream(array,from,to)可以用数组…

uniapp:微信小程序文本长按无法出现复制菜单

一、问题描述 在集成腾讯TUI后&#xff0c;为了能让聊天文本可以复制&#xff0c;对消息组件的样式进行修改&#xff0c;主要是移除下面的user-select属性限制&#xff1a; user-select: none;-webkit-user-select: none;-khtml-user-select: none;-moz-user-select: none;-ms…

UFS供电

UFS device结构图如上所示&#xff0c;可以看到有三路电源&#xff1a;VCC&#xff0c;VCCQ和VCCQ2。定义如下&#xff1a; 这三路电压参数如下&#xff1a; 上电时序如下所示&#xff1a; 但实际使用的UFS device产品&#xff0c;可能与spce略有不同。我看到的几款三星、美光和…

c++类和对象(六个默认成员函数)

文章目录 一.类的六个默认成员函数二.构造函数1.概念2.特性 三.析构函数1.概念2.特性 四.拷贝构造函数1.概念2.特性 五.赋值操作符重载5.1运算符重载5.2 赋值运算符重载 一.类的六个默认成员函数 如果一个类中什么成员都没有&#xff0c;简称为空类。空类中什么都没有吗&#x…

互联网直播点播平台EasyDSS无人机视频推拉流技术实现工地远程监控巡检直播

在建筑行业&#xff0c;施工现场的安全管理和实时监控一直是项目管理中的重点。随着技术的进步&#xff0c;无人机工地直播技术成为了一种新兴的解决方案&#xff0c;它不仅能够提高施工透明度&#xff0c;还能够加强现场安全管理。EasyDSS作为一种先进的流媒体技术平台&#x…

如何使用网络工具进行网络性能评估

网络评估是对IT基础设施的系统评估&#xff0c;以确保它能够很好地满足企业的核心运营需求&#xff0c;确定了基础设施中需要改进的领域&#xff0c;并定义了改进的范围。 网络评估工具分析IT基础设施的各个方面&#xff0c;它通过评估网络设备、网络性能和安全威胁来仔细检查…

【Java项目】基于SpringBoot的【人职匹配推荐系统】

【Java项目】基于SpringBoot的【人职匹配推荐系统】 技术简介&#xff1a;本系统使用采用B/S架构、Spring Boot框架、MYSQL数据库进行开发设计。 系统简介&#xff1a;人职匹配推荐系统分为管理员和用户、企业三个权限子模块。 管理员所能使用的功能主要有&#xff1a;首页、个…

ROS2+OpenCV综合应用--10. AprilTag标签码追踪

1. 简介 apriltag标签码追踪是在apriltag标签码识别的基础上&#xff0c;增加了小车摄像头云台运动的功能&#xff0c;摄像头会保持标签码在视觉中间而运动&#xff0c;根据这一特性&#xff0c;从而实现标签码追踪功能。 2. 启动 2.1 程序启动前的准备 本次apriltag标签码使…

【Vim Masterclass 笔记03】S03L10 + S03L11:Vim 中的文本删除操作以及 Vim 思维习惯的培养(含 DIY 拓展知识点)

文章目录 Section 3&#xff1a;Vim Essentials&#xff08;Vim 核心知识&#xff09;S03L10 Vim 核心浏览命令同步练习点评课S03L11 Deleting Text and "Thinking in Vim" 文本的删除及 Vim 思维习惯的培养1 删除单个字符2 删除一个单词2.1 推广1&#xff1a;D HJK…

【时时三省】(C语言基础)动态内存函数calloc

山不在高&#xff0c;有仙则名。水不在深&#xff0c;有龙则灵。 ----CSDN 时时三省 calloc calloc函数也用来动态内存分配 原型如下: void* calloc&#xff08;size&#xff3f;t num, size&#xff3f;t size&#xff09;&#xff1b; 它们两个的区别是 它是需要两个参数…

LeetCode - 初级算法 数组(两个数组的交集 II)

两个数组的交集 II 这篇文章讨论如何求两个数组的交集,并返回结果中每个元素出现的次数与其在两个数组中都出现的次数一致。提供多个实现方法以满足不同场景需求。 免责声明:本文来源于个人知识与公开资料,仅用于学术交流。 描述 给定两个整数数组 nums1 和 nums2,以数…

[react]小技巧, ts如何声明点击事件的类型

很简单, 鼠标放到事件上面就行了 如果想知道点击的是什么元素 ,打印他的nodename就行了 不过得断言为html元素才行 const handleClick (e: React.MouseEvent<HTMLDivElement, MouseEvent>) > {console.log(current, (e.target as HTMLElement).nodeName);}; 为什么…

[创业之路-229]:《华为闭环战略管理》-5-平衡记分卡与战略地图

目录 一、平衡记分卡 1. 财务角度&#xff1a; 2. 客户角度&#xff1a; 3. 内部运营角度&#xff1a; 4. 学习与成长角度&#xff1a; 二、BSC战略地图 1、核心内容 2、绘制目的 3、绘制方法 4、注意事项 一、平衡记分卡 平衡记分卡&#xff08;Balanced Scorecard&…

【中间件】docker+kafka单节点部署---zookeeper模式

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言消息中间件介绍1. KRaft模式2. zookeeper模式2.1. 单节点部署安装验证 前言 最近生产环境上准备部署ELFK日志监控&#xff0c;先在测试环境部署单节点kafka验证…