原理
1、文件上传(File Upload)是大部分Web应用都具备的功能,例如用户上传附 件、修改头像、分享图片/视频等
2、正常的文件一般是文档、图片、视频等,Web应用收集之后放入后台存储, 需要的时候再调用出来返回
3、如果恶意文件如PHP、ASP等执行文件绕过Web应用,并顺利执行,则相当 于黑客直接拿到了Webshell
4、一旦黑客拿到Webshell,则可以拿到Web应用的数据,删除Web文件,甚至本地提权,进一步拿下整个服务器甚至内网渗tou
5、SQL注入公鸡的对象是数据库服务,文件上传漏洞主要公鸡Web服务,实际 渗tou过程一般结合起来,达到对目标服务的深度控制
深入原理:
文件上传的原理是客户端将文件数据通过HTTP协议POST请求发送到服务器,服务器接收到请求后,解析请求头和请求体,从请求体中获取文件数据并保存到服务器本地磁盘上。具体步骤如下:
1.客户端通过form表单将文件数据封装成HTTP请求发送到服务器。
2.服务器接收到请求后,解析请求头和请求体。
3.从请求体中获取文件数据。
4.将文件数据保存到服务器本地磁盘上。
以下是一个Java Servlet文件上传的例子:
import java.io.File; import java.io.IOException; import java.io.PrintWriter; import java.util.List; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; @WebServlet("/upload") public class FileUploadServlet extends HttpServlet { private static final long serialVersionUID = 1L; private static final String UPLOAD_DIRECTORY = "uploads"; private static final int MEMORY_THRESHOLD = 1024 * 1024 * 3; // 3MB private static final int MAX_FILE_SIZE = 1024 * 1024 * 40; // 40MB private static final int MAX_REQUEST_SIZE = 1024 * 1024 * 50; // 50MB protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 检查是否为文件上传请求 if (!ServletFileUpload.isMultipartContent(request)) { PrintWriter writer = response.getWriter(); writer.println("Error: 表单必须包含 enctype=multipart/form-data"); writer.flush(); return; } // 配置上传参数 DiskFileItemFactory factory = new DiskFileItemFactory(); factory.setSizeThreshold(MEMORY_THRESHOLD); factory.setRepository(new File(System.getProperty("java.io.tmpdir"))); ServletFileUpload upload = new ServletFileUpload(factory); upload.setFileSizeMax(MAX_FILE_SIZE); upload.setSizeMax(MAX_REQUEST_SIZE); // 构造服务器本地保存路径 String uploadPath = getServletContext().getRealPath("") + File.separator + UPLOAD_DIRECTORY; // 创建保存路径目录 File uploadDir = new File(uploadPath); if (!uploadDir.exists()) { uploadDir.mkdir(); } try { // 解析请求的内容提取文件数据 List<FileItem> formItems = upload.parseRequest(request); if (formItems != null && formItems.size() > 0) { // 迭代表单数据 for (FileItem item : formItems) { // 处理不在表单中的字段 if (!item.isFormField()) { String fileName = new File(item.getName()).getName(); String filePath = uploadPath + File.separator + fileName; File storeFile = new File(filePath); // 在控制台输出文件的上传路径 System.out.println(filePath); // 保存文件到硬盘 item.write(storeFile); request.setAttribute("message", "文件上传成功!"); } } } } catch (Exception ex) { request.setAttribute("message", "错误信息: " + ex.getMessage()); } // 跳转到结果页面 getServletContext().getRequestDispatcher("/result.jsp").forward(request, response); } }
低安全级别
选择低安全级别
访问文件上传页面
上传图片或者文本文件
上传测试图片
上传成功
分析文件上传后台代码
低安全级别的文件上传(后台)代码,没有做任何的安全过滤,
包括文件类型、文件后缀、大小等等
文件上传漏洞利用
上传超大型文件
消耗服务器资源
之前查看后台代码,没有做任何限制的,为什么 这里不给上传呢?既然后台没有做限制,那么应 该是前端代码做了限制
绕过前端限制有N多种方法,可以直接在浏览器 插件通过firebug修改value值,也可以通过burp拦 截POST修改之后再发送
上传Webshell(挂马)