揭秘文件上传漏洞之操作原理(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.mzph.cn/bicheng/65717.shtml

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

相关文章

《迁移学习与联邦学习:推动人工智能发展的关键力量》

在人工智能的发展历程中&#xff0c;数据和模型的学习方式不断演进。迁移学习和联邦学习作为两种重要的技术&#xff0c;正逐渐成为行业关注的焦点。 迁移学习&#xff1a;跨越边界的智慧 迁移学习旨在将从一个任务中学习到的知识迁移到另一个相关任务中。简单来说&#xff0…

哈夫曼编码(Huffman Coding)与哈夫曼树(Huffman Tree)

已知字符集{a,b,c,d,e,f}&#xff0c;若各字符出现的次数分别为6&#xff0c;3&#xff0c;8&#xff0c;2&#xff0c;10&#xff0c;4&#xff0c;则对应字符集中各字符的哈夫曼编码可能是&#xff08; &#xff09;。 A.00&#xff0c;1011&#xff0c;01&#xff0…

R语言入门笔记:第一节,快速了解R语言——文件与基础操作

关于 R 语言的简单介绍 上一期 R 语言入门笔记里面我简单介绍了 R 语言的安装和使用方法&#xff0c;以及各项避免踩坑的注意事项。我想把这个系列的笔记持续写下去。 这份笔记只是我的 R 语言入门学习笔记&#xff0c;而不是一套 R 语言教程。换句话说&#xff1a;这份笔记不…

创意思维与决策方法——SCAMPER:探索创新思维的利器

探索创新思维的利器&#xff1a;SCAMPER法 在面对复杂问题或需要突破性创意时&#xff0c;我们常常需要一些行之有效的工具来引导思考。SCAMPER法正是这样一个激发创新思维的利器&#xff0c;它通过七个步骤&#xff1a;替代&#xff08;Substitute&#xff09;、组合&#xf…

微信小程序调用 WebAssembly 烹饪指南

我们都是在夜里崩溃过的俗人&#xff0c;所幸终会天亮。明天就是新的开始&#xff0c;我们会变得与昨天不同。 一、Rust 导出 wasm 参考 wasm-bindgen 官方指南 https://wasm.rust-lang.net.cn/wasm-bindgen/introduction.html wasm-bindgen&#xff0c;这是一个 Rust 库和 CLI…

自动驾驶3D目标检测综述(六)

停更了好久终于回来了&#xff08;其实是因为博主去备考期末了hh&#xff09; 这一篇接着&#xff08;五&#xff09;的第七章开始讲述第八章的内容。第八章主要介绍的是三维目标检测的高效标签。 目录 第八章 三维目标检测高效标签 一、域适应 &#xff08;一&#xff09;…

计算机毕业设计hadoop+spark+hive图书推荐系统 豆瓣图书数据分析可视化大屏 豆瓣图书爬虫 知识图谱 图书大数据 大数据毕业设计 机器学习

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

极品飞车6的游戏手柄设置

极品飞车&#xff0c;既可以用键盘来控制车辆的前进、后退、左转、右转、加速与减速&#xff0c;也可以使用游戏手柄来操作车辆的运行。需要注意的是&#xff0c;极品飞车虽然支持手柄&#xff0c;但是仅支持常见的北通、罗技还有部分Xbox系列的手柄&#xff0c;至于其他的PS4手…

【VBA】EXCEL - VBA 创建 Sheet 表的 6 种方法,以及注意事项

目录 1. 创建一个新工作表&#xff0c;并将其添加到工作簿的末尾 2. 创建一个新工作表&#xff0c;并命名它 3. 创建一个新工作表&#xff0c;并将其插入到指定位置 4. 检查是否已有同名工作表&#xff0c;避免重复创建 5. 创建多个工作表 6. 基于现有模板创建新工作表 …

html文件通过script标签引入外部js文件,但没正确加载的原因

移动端H5应用&#xff0c;html文件通过script标签引入外部js文件&#xff0c;但没正确加载&#xff0c;在移动设备上难以排查。通过PC浏览器打开&#xff0c;发现js被阻止了&#xff1a;blocked:mixed-content。 原因在于&#xff1a; “blocked:mixed - content” 是浏览器的…

虚拟机Centos下安装Mysql完整过程(图文详解)

目录 一. 准备工作 1. 设置虚拟机静态IP 2. 卸载Mysql 3. 给CentOS添加rpm源 二. 安装MySQL 1. 安装mysql服务 2. 启动mysql服务 3. 开启MySQL开机自启动 4. 查看mysql服务状态 5. 查看mysql初始密码 6. 登录mysql &#xff0c;修改密码 7. 允许外部访问MySQL数据库…

ulimit命令与nginx的联系

华子目录 ulimit使用ulimit命令查看当前限制设置特定限制常用的资源类型临时和永久设置 ulimit与nginx的联系ulimit对Nginx的影响Nginx配置中的相关参数 ulimit 在Linux系统中&#xff0c;ulimit命令用于获取和设置用户级别的资源使用限制。这些限制可以控制诸如可以打开的文件…

初识具身智能

具身智能是智能科学的一个基础问题&#xff0c;在过去的5.4亿年以来&#xff0c;地球上所有生物都是通过身体和环境交互、进化逐步产生的。通俗地讲&#xff0c;具身智能体以第一人称视角身临其境地从环境交互中理解外部世界的本质概念&#xff0c;被认为是通向通用人工智能的重…

【机器人】机器人的数学模型:符号表示、位形空间、状态空间、工作空间

定义 机器人是一种可重复编程的多功能机械臂&#xff0c;他们通过可变程控运动来执行如移动材料、零件、工具或者特种设备等多种任务。 ——美国机器人协会&#xff08;RIA&#xff09; 1.1 机器人的数学模型 1.1.1 机器人的符号表示 机械臂&#xff1a;关节joint 连杆link …

VITUREMEIG | AR眼镜 算力增程

根据IDC发布的《2024年第三季度美国AR/VR市场报告》显示&#xff0c;美国市场AR/VR总出货量增长10.3%。其中&#xff0c;成立于2021年的VITURE增长速度令人惊艳&#xff0c;同比暴涨452.6%&#xff0c;成为历史上增长最快的AR/VR品牌。并在美国AR领域占据了超过50%的市场份额&a…

PY_11_01

前言 PY_11_01 抄就行了&#x1f47b; 一、代码步骤 抄就行了&#x1f47b; def fact(n):if n1:return 1else:return n*fact(n-1)while True:minput(请输入一个正整数m:)if not m.isdigit() or int(m)0:print(输入错误&#xff0c;请重新输入&#xff01;)else:mint(m)brea…

Richardson-Lucy (RL) 算法的卷积形式推导

Richardson-Lucy 算法从模糊图像中恢复原始图像。Richardson-Lucy 方法假设观测图像的噪声服从泊松分布&#xff0c;是一种极大似然估计方法。 1. 问题定义 假设我们有一个原始图像 f ( x , y ) f(x,y) f(x,y)&#xff0c;通过一个已知的点扩散函数 h ( x , y ) h(x,y) h(x,y…

网线直连模式下,ubuntu虚拟机与zynq开发板互ping

目的&#xff1a;想要使用网线将windows网口与zynq开发板网口直连&#xff0c;可以实现通过nfs&#xff08;network file system)挂载在ubuntu中的根文件系统&#xff0c;从而运行linux&#xff0c;方便linux的驱动开发。 参考文章&#xff1a; 领航者 ZYNQ 之嵌入式 Linux 开…

深入了解 Zookeeper:原理与应用(选举篇)

在上一篇关于 Zookeeper 的介绍中&#xff0c;我们知晓了它在分布式系统中的关键地位以及核心的工作原理框架。今天&#xff0c;重点来深入探究一下 Zookeeper 集群是如何实现领导者选举这一至关重要的环节的。 一、选举触发时机 集群启动时&#xff1a;当一个全新的 Zookeep…

金仓数据库对象访问权限的管理

基础知识 对象的分类 数据库的表、索引、视图、缺省值、规则、触发器等等&#xff0c;都称为数据库对象&#xff0c;对象分为如下两类: 模式(SCHEMA)对象:可以理解为一个存储目录&#xff0c;包含视图、索引、数据类型、函数和操作符等。非模式对象:其他的数据库对象&#x…