【上传专题】仅前端过滤

    在论坛等平台中,上传各种附件是必不可少的功能,往往也是黑客们容易攻击的地方。在上传专题中,与大家分享一些关于如何破解上传,以及如何防御,通过两者的博弈方式,体现出上传附件攻防的微妙之处。

    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,或者一些其他恶意的操作。这一系列的文章,重点是讲述如何使用上传组件,以及如何防御非法上传。在下一篇文章中,将介绍如何后端代码过滤扩展名,以及相应的问题。

    

本文出自 “java程序冥” 博客,请务必保留此出处http://793404905.blog.51cto.com/6179428/1566743

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。