当前位置: 首页 > news >正文

ASP.NET 上传文件安全检测方案

一、前端初步过滤(防误操作)

<!-- HTML部分 --><input type="file" id="fileUpload" accept=".jpg,.png,.pdf,.docx" /><button onclick="validateFile()">上传</button><script>functionvalidateFile(){const file = document.getElementById('fileUpload').files[0];if (!file) return alert('请选择文件');// 检查文件扩展名const allowedExtensions = /(\.jpg|\.png|\.pdf|\.docx)$/i;if (!allowedExtensions.test(file.name)){ alert('不允许的文件类型'); return false; }// 检查文件大小(示例:限制20MB)if (file.size > 20 * 1024 * 1024){ alert('文件超过20MB'); return false; }// 提交表单document.getElementById('uploadForm').submit();}</script>

二、后端深度验证(核心防御)

// 1. 验证文件扩展名(双重验证,防止绕过前端)

// 2. 验证MIME类型(检查Content-Type头)

// 3. 验证文件内容(魔数检测)

// 4. 扫描文件是否包含恶意代码(示例:检查HTML文件中的脚本标签)

// 5. 保存文件到安全位置(禁用执行权限)

// ASP.NET MVC控制器示例[HttpPost][ValidateAntiForgeryToken]public ActionResult Upload(HttpPostedFileBase file){if (file == null || file.ContentLength == 0)return Json(new { success = false, message = "请选择文件" });try{// 1. 验证文件扩展名(双重验证,防止绕过前端)var allowedExtensions = new[] { ".jpg", ".png", ".pdf", ".docx" };var fileExtension = Path.GetExtension(file.FileName).ToLowerInvariant();if (!allowedExtensions.Contains(fileExtension))return Json(new { success = false, message = "文件类型不允许" });// 2. 验证MIME类型(检查Content-Type头)if (!IsValidMimeType(file.ContentType, fileExtension))return Json(new { success = false, message = "文件类型不匹配" });// 3. 验证文件内容(魔数检测)if (!IsValidFileContent(file.InputStream, fileExtension))return Json(new { success = false, message = "文件内容异常" });// 4. 扫描文件是否包含恶意代码(示例:检查HTML文件中的脚本标签)if (fileExtension == ".html" && ContainsMaliciousCode(file.InputStream))return Json(new { success = false, message = "文件包含恶意代码" });// 5. 保存文件到安全位置(禁用执行权限)var fileName = Guid.NewGuid().ToString() + fileExtension;var filePath = Path.Combine(Server.MapPath("~/Uploads/"), fileName);file.SaveAs(filePath);return Json(new { success = true, message = "上传成功" });}catch (Exception ex){// 记录详细日志(包含文件名、大小、时间戳等)Logger.Error($"文件上传失败: {ex.Message}", ex);return Json(new { success = false, message = "上传过程中发生错误" });}}// 验证MIME类型private bool IsValidMimeType(string contentType, string fileExtension){var allowedMimeTypes = new Dictionary<string, string[]>{{ ".jpg", new[] { "image/jpeg", "image/pjpeg" } },{ ".png", new[] { "image/png" } },{ ".pdf", new[] { "application/pdf" } },{ ".docx", new[] { "application/vnd.openxmlformats-officedocument.wordprocessingml.document" } }};if (!allowedMimeTypes.ContainsKey(fileExtension))return false;return allowedMimeTypes[fileExtension].Contains(contentType);}// 验证文件内容(魔数检测)private bool IsValidFileContent(Stream stream, string fileExtension){// 重置流位置stream.Position = 0;// 读取文件前几个字节(魔数)var buffer = new byte[8];stream.Read(buffer, 0, buffer.Length);stream.Position = 0; // 重置流位置供后续使用// 根据文件类型检查魔数switch (fileExtension){case ".jpg":// JPEG魔数: FF D8 FFreturn buffer[0] == 0xFF && buffer[1] == 0xD8 && buffer[2] == 0xFF;case ".png":// PNG魔数: 89 50 4E 47 0D 0A 1A 0Areturn buffer[0] == 0x89 && buffer[1] == 0x50 && buffer[2] == 0x4E && buffer[3] == 0x47 && buffer[4] == 0x0D && buffer[5] == 0x0A &&                   buffer[6] == 0x1A && buffer[7] == 0x0A;    case ".pdf":// PDF魔数: 25 50 44 46return buffer[0] == 0x25 && buffer[1] == 0x50 && buffer[2] == 0x44 && buffer[3] == 0x46;default:// 其他类型可以添加更多检查return true;}}// 检查文件是否包含恶意代码(示例:HTML文件)private bool ContainsMaliciousCode(Stream stream){using (var reader = new StreamReader(stream)){var content = reader.ReadToEnd();stream.Position = 0; // 重置流位置// 检测常见的恶意代码模式//在这里增加被攻击的恶意代码var maliciousPatterns = new[] {@"<script\s*[^>]*>",@"vbscript:",@"onerror\s*=",@"<iframe\s*[^>]*>"};return maliciousPatterns.Any(pattern =>Regex.IsMatch(content, pattern, RegexOptions.IgnoreCase));}}@"<?xml", // XML注入@"<!DOCTYPE", // XXE攻击@"<script", // 脚本注入@"<img", // 图片标签注入@"<iframe", // iframe注入@"<object", // object标签@"<embed", // embed标签@"<applet", // applet标签@"<form", // form标签@"<input", // input标签@"<link", // link标签@"<style", // style标签@"<svg", // SVG注入@"<math", // MathML注入@"onerror", // 事件处理器@"onload", // 事件处理器@"javascript:", // JS协议@"data:text/html", // data协议@"base64,", // base64编码@"eval(", // eval函数@"expression(", // CSS表达式@"alert(", // alert函数@"document.cookie", // 访问cookie@"window.location", // 重定向@"window.open", // 弹窗@"fetch(", // fetch API@"XMLHttpRequest", // AJAX@"ActiveXObject", // ActiveX@"<meta", // meta标签@"<body", // body标签@"<head", // head标签@"<title", // title标签@"<audio", // audio标签@"<video", // video标签@"<source", // source标签@"<track", // track标签@"<marquee", // marquee标签@"<blink", // blink标签@"<bgsound", // bgsound标签@"<frame", // frame标签@"<frameset", // frameset标签@"<noscript", // noscript标签@"<plaintext", // plaintext标签@"<xss", // xss标签@"vbscript:", // vbscript协议@"mocha:", // mocha协议@"livescript:", // livescript协议@"<!--", // 注释@"-->", // 注释@"<%=", // ASP/模板注入@"<?php", // PHP代码// @"<%!", // JSP/模板注入@"<%#", // ASP.NET模板注入@"<%$", // ASP.NET模板注入@"<%:", // ASP.NET模板注入@"<%?", // 模板注入@"<%--", // 注释@"<%>", // 模板@"<c:", // JSTL标签@"<jsp:", // JSP标签@"<s:", // Struts标签// @"<%@", // 指令// @"<#", // Freemarker@"#include", // SSI@"system(", // 系统命令@"exec(", // 系统命令@"passthru(", // 系统命令@"shell_exec(", // 系统命令@"popen(", // 系统命令@"proc_open(", // 系统命令@"require", // PHP@"include", // PHP@"require_once", // PHP@"include_once", // PHP@"import", // Python/JS// @"from", // Python@"os.system", // Python@"subprocess", // Python@"rm -rf", // Linux命令@"del ", // Windows命令@"request",@"eval",@"cmd"

http://www.xdnf.cn/news/1291591.html

相关文章:

  • 设计秒杀系统从哪些方面考虑
  • 微软正式将GPT-5接入Microsoft Copilot Studio(国际版)
  • 【物联网】基于树莓派的物联网开发【26】——树莓派开启串口并配置串口助手Minicom
  • jvm学习笔记之jvm的生命周期和发展历程
  • Ansible 实操笔记:Playbook 与变量管理
  • dubbo应用之门面设计模式
  • 《Python学习之基础语法2:掌握程序流程控制的艺术》
  • 101、【OS】【Nuttx】【周边】文档构建渲染:reStructuredText 格式
  • 【C语言强化训练16天】--从基础到进阶的蜕变之旅:Day3
  • C++多态:理解面向对象的“一个接口,多种实现”
  • 《AVL树的原理与C++实现:详解平衡二叉搜索树的高效构建与操作》
  • 旧版MinIO的安装(windows)、Spring Boot 后端集成 MinIO 实现文件存储(超详细,带图文)
  • 使用 6 种方法将文件从 Android 无缝传输到iPad
  • [Linux]学习笔记系列 -- [arm][process]
  • WPF 开发的瑞士军刀:Prism 框架从入门到精通指南
  • C++写文件,open函数的参数in、out、ate、app、trunc等标志分别是什么作用?
  • C++ 面向对象四大特性:面试深度解析
  • 河南萌新联赛2025第五场 - 信息工程大学
  • IDEA创建一个VUE项目
  • C# 微软依赖注入 (Microsoft.Extensions.DependencyInjection) 详解
  • 数据分析项目----幸福感挖掘和预测
  • Python实战教程:PDF文档自动化编辑与图表绘制全攻略
  • PyTorch生成式人工智能——基于Transformer实现文本转语音
  • SeaTunnel MCP Server 入选《中国信通院开源商业产品及企业典型案例集(2025)》
  • 袖珍手持气象仪的用途
  • linux_网络层-ip协议
  • 开源日志log4cplus—调用MultiByteToWideChar提示未定义,CP_UTF8未定义定原因有哪些,如何改进?
  • 【安卓,问题记录】ImageView 在布局顺序上位于 Button 上方,却出现图像内容被 Button 遮挡
  • 北京JAVA基础面试30天打卡09
  • ELK开启安全策略