在论坛等平台中,上传各种附件是必不可少的功能,往往也是黑客们容易攻击的地方。在上传专题中,与大家分享一些关于如何破解上传,以及如何防御,通过两者的博弈方式,体现出上传附件攻防的微妙之处。
1. 概述
本文介绍前端过滤上传附件扩展名,如何使用burosuite绕过前端过滤,上传非法文件。
2. 前提条件
1)burpsuite工具;
2)apache commons fileupload 相关jar包;
3. 前端代码示例
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>My JSP ‘index.jsp‘ starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <script type="text/javascript"> // submit upload form function upload() { // 获取上传文件名 var filename = document.getElementById("filename").value; // 判断上传文件是否是jpg扩展名,如果是那么提交表单,否则提示用户上传文件非法 if (filename.lastIndexOf(".jpg") != -1) { document.forms[0].action = "upload.do"; document.forms[0].submit(); }else { alert("Only jpg "); window.open(window.location.href, _self); } } </script> </head> <body> <form enctype="multipart/form-data" method="post"> fileDesc : <input type="text" name="fileDesc" id="fileDesc"><br/> fileupload : <input type="file" name="filename" id="filename"><br/> <input type="submit" value="Upload" onclick="upload();"> </form> </body> </html>
4. 后台上传处理代码示例
package com.fileupload.servlets; import java.io.File; import java.io.IOException; import java.util.List; import javax.servlet.ServletException; 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.FileUploadException; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; /** * 文件上传 * @author wangzp * */ public class UploadServlet extends HttpServlet { /** 内存容量阀值 **/ private final int sizeThreshold = 1024 * 1024 * 2; public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 判断是否是multipart/form-data请求 boolean isMultipartRequest = ServletFileUpload.isMultipartContent(request); if (!isMultipartRequest) { response.getWriter().print("Invalid Request"); return; } String tmpPath = this.getServletContext().getRealPath("/images"); DiskFileItemFactory factory = new DiskFileItemFactory(sizeThreshold, new File(tmpPath)); ServletFileUpload fileUpload = new ServletFileUpload(factory); fileUpload.setFileSizeMax(1024 * 1024 * 5); // 单个上传文件的大小上限 fileUpload.setSizeMax(1024 * 1024 * 5); // 一次请求字节大小上限 fileUpload.setHeaderEncoding("utf-8"); // 设置请求头编码 try { // 解析请求返回表单字段域对应的FileItem列表;每一个表单字段对应一个FileItem实例 List<FileItem> fileItems = fileUpload.parseRequest(request); for (FileItem fileItem : fileItems) { // 获取表单字段的name属性 String fieldName = fileItem.getFieldName(); // 获取上传文件的文件名,如果是非上传文件字段,那么该值为null; String name = fileItem.getName(); // 获取字段对应的值 String value = fileItem.getString(); // 如果是上传字段,那么会获取ContentType类型,非上传字段返回null; System.out.println(fileItem.getContentType()); if (fileItem.isFormField()) { // true : 非上传字段 response.getWriter().println(fieldName + " : " + value); }else { //如果是文件上传字段 System.out.println("fieldName : " + fieldName); System.out.println("name:" + name); File file = new File(tmpPath + "/" + name); if (!file.getParentFile().exists()) { file.getParentFile().mkdir(); } fileItem.write(file); } } } catch (FileUploadException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } }
5.结果分析以及如何绕过前端过滤
当上传.jpg图片时,可以成功上传文件,当选择其他文件时,前端会提示上传文件类型不正确;那么如何才能绕过前端的过程呢?如果对拦截工具有些了解的话,这是很简单的事情,可以采取如下方式:
1)修改文件扩展名,例如:原文件为test.png,将其修改为test.png.jpg;这时前端就可以验证成功,即可以顺利的出发表单提交;
2)使用burpsuite拦截文件上传请求,如下图:
在修改后,可以让其提交到到服务器,你会发现服务器成功上传了redis.png图片。
6. 总结
这只是一个简单的例子,现在的开发网站不大会这么简单就可以绕过的,关于更加复杂的问题,会 在后续的文章中,逐一介绍。
作为后端开发人员,不应该去依赖前端的代码控制,因为暴露给用户的代码,不会是安全的;那往往是一种用户体验的措施,因此面对这样的情况,后端应该也做足功课,对上传文件的信息过滤处理;尽可能的防止上传非法文件,如果让其上传了非法文件,对方极有可能获取WebShell,或者一些其他恶意的操作。这一系列的文章,重点是讲述如何使用上传组件,以及如何防御非法上传。在下一篇文章中,将介绍如何后端代码过滤扩展名,以及相应的问题。
时间: 2024-10-09 19:32:05