原理
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修改之后再发送