文件上传下载中的安全问题(上传漏洞与目录遍历攻击)

前言

文件上传与下载是项目中经常需要提供的功能,不管是哪个web应用几乎都可以找到.那本屌今天就来说一说我们在开发中的疏忽可能导致的问题.

先建立一个web工程,目录结构如下

技术分享


文件上传漏洞

我们来看看下面这段文件上传代码,使用的是common-fileupload.jar 和common-io.jar
UploadServlet.java 访问路径/UploadServlet
/**
	 * 文件上传
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) {
		String root = request.getServletContext().getRealPath("/upload");
		DiskFileItemFactory factory = new DiskFileItemFactory();
		ServletFileUpload upload = new ServletFileUpload(factory);
		try {
			List<FileItem> list = upload.parseRequest(request);
			for(FileItem it:list){
				//如果是file文件类型
				if(!it.isFormField()){
					it.write(new File(root+"/"+it.getName()));
					response.getWriter().write("success");
				}
			}
		} catch (Exception e) {
			try {
				response.getWriter().write("exception");
			} catch (IOException e1) {
				e1.printStackTrace();
			}
			e.printStackTrace();
			
		}
		
	}
前端index.jsp有一个上传文件的表单
<form  action="/load/UploadServlet" method="post" enctype="multipart/form-data">
		<input type="file" name="file"/>
		<input type="submit" value="submit"/>		
</form>
我们将项目发布到tomcat并且访问http://localhost:8080/load/
技术分享
技术分享
选择要上传的文件提交表单.文件上传也成功,在upload目录下也有我们所上传的文件.
(如果是你一个刚毕业刚入行的新人,你可能看不出任何问题),可能很多老鸟大神都知道这个上传功能存在什么问题,要骂我sb(我回复 fuck you).
对没错,这个功能还有一个最大的问题就是没有对上传的文件格式做限制,如果我这里实现写好了一个脚本a.jsp代码如下
a.jsp
<%@page import="java.io.File"%>
<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<%
	String root = request.getServletContext().getRealPath("");
	out.write("系统部署绝对路径:"+root);
	File file = new File(root+"/index.jsp");
	file.delete();
%>
上传完毕,我们在访问localhost:8080/load/upload/a.jsp,然后你在返回你就会发现一件恐怖的事情,这里不限于做删除操作,还可以自定义主页,看你自己怎么写了
所以说我们在做上传的时候必须要对上传的文件格式做处理,在上传的时候加入一句判断语句(当然只判断后缀,还可能存在一些问题,最好在加上判断文件前4个字节一起判断[不同文件类型前4字节不同]),这样就能很好的避免上述问题
//根据业务不同自定义
				if(it.getName().contains("jsp")){
					//return
				}

文件下载漏洞(目录遍历攻击)

下面再来看看文件下载中的安全问题
DownLoad.java  访问路径 /DownLoad
  /**
     * 文件下载
     */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//获取项目部署绝对路径下的upload文件夹路径
		String root = request.getServletContext().getRealPath("/upload");
		//获取文件名
		String filename = request.getParameter("filename");
		File file = new File(root+"/"+filename);
		FileInputStream fis = new FileInputStream(file);
		response.addHeader("Content-Disposition", "attachment;filename=" + new String(filename.getBytes()));
        response.addHeader("Content-Length", "" + file.length());
        byte[] b = new byte[fis.available()];
        fis.read(b);
        response.getOutputStream().write(b);
        
	}
index.jsp 加入一个新表单
<form  action="/load/DownLoad" method="get">
		需要下载的文件名称<input type="text" name="filename"/>
		<input type="submit" value="submit"/>		
</form>

技术分享
http://localhost:8080/load/DownLoad?filename=download.txt
这里我们输入要下载的文件名,submit后会访问后台的DownLoad,DownLoad里面我们获取文件名称,然后获取输入输出流对文件进行下载.操作结果成功下载文件
技术分享
上述的下载代码90%的人都是那样写的,里面的问题就不是那么容易看出来了,尽管你可能已经工作的有些时候了.
下面在文本框中输入[../WEB-INF/web.xml],submit后,你就会下载到一个很技术分享的文件!
技术分享
这里不限于../ 还能更多上下级目录,这就是"目录遍历攻击",大家可以在百度去看看相关的知识.至于解决方案大家多半也知道了需要对文件名称进行特殊字母的判断.(你写的代码存在这个问题吗?)

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