从Java的角度谈下文件下载漏洞的产生,然后到他的修复方案。这里我的修复方案是白名单,而没有采用黑名单的方式。

  首先先看一段存在文件下载漏洞的代码code:

    HTML视图页面  download.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>使用a标签直接指向服务器上的资源</h1>
<a href="/WEB14/download/a.flv">a.flv</a><br>
<a href="/WEB14/download/a.jpg">a.jpg</a><br>
<a href="/WEB14/download/a.mp3">a.mp3</a><br>
<a href="/WEB14/download/a.mp4">a.mp4</a><br>
<a href="/WEB14/download/a.txt">a.txt</a><br>
<a href="/WEB14/download/a.zip">a.zip</a><br>
<h1>使用服务器端编码的方式实现文件下载</h1>
<a href="/WEB14/downloadServlet2?filename=a.flv">a.flv</a><br>
<a href="/WEB14/downloadServlet2?filename=a.jpg">a.jpg</a><br>
<a href="/WEB14/downloadServlet2?filename=a.mp3">a.mp3</a><br>
<a href="/WEB14/downloadServlet2?filename=a.mp4">a.mp4</a><br>
<a href="/WEB14/downloadServlet2?filename=a.txt">a.txt</a><br>
<a href="/WEB14/downloadServlet2?filename=a.zip">a.zip</a><br>
<a href="/WEB14/downloadServlet2?filename=美女.jpg">美女.jpg</a><br>
</body>
</html>

  服务器端验证文件下载代码:

    downloadServlet2.java代码如下:

        

package cn.downloadServlet;

import java.io.*;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Base64; import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.ws.RespectBinding; import com.sun.org.apache.xerces.internal.util.SynchronizedSymbolTable;
import com.sun.xml.internal.bind.v2.runtime.output.StAXExStreamWriterOutput; import sun.misc.BASE64Encoder; public class DownloadServlet2 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 请求filename参数
String filename = request.getParameter("filename");
// System.out.println(filename);
// 解决获得中文参数的乱码
filename = new String(filename.getBytes("ISO8859-1"), "UTF-8");
// 获得请求头中的User-Agent
String agent = request.getHeader("User-Agent");
// 根据不同浏览器进行不同的编码
String filenameEncoder = "";
if (agent.contains("MSIE")) {
// IE浏览器
filenameEncoder = URLEncoder.encode(filename, "utf-8");
filenameEncoder = filenameEncoder.replace("+", " ");
} else if (agent.contains("Firefox")) {
// 火狐浏览器
BASE64Encoder base64Encoder = new BASE64Encoder();
filenameEncoder = "=?utf-8?B?" + base64Encoder.encode(filename.getBytes("utf-8")) + "?=";
} else {
// 其它浏览器
filenameEncoder = URLEncoder.encode(filename, "utf-8");
}
String requestURI = request.getRequestURI();
System.out.println(requestURI);
// 自动判断文件的数据类型
response.setContentType(this.getServletContext().getMimeType(filename));
// 告诉客户端该文件不是直接解析 而是以附件形式打开(下载)
response.setHeader("Content-Disposition", "attachment;filename=" + filenameEncoder);
//获取请求的文件路径名称
String realPath = this.getServletContext().getRealPath("/download/" + filename);
ServletOutputStream outputStream = response.getOutputStream();
FileInputStream fileInputStream = new FileInputStream(realPath);
int length = 0;
byte[] buff = new byte[1024];
while ((length = fileInputStream.read(buff)) != -1) {
outputStream.write(buff, 0, length);
}
} public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}

  这段代码是是存在漏洞的,这里获取filename参数的时候未进行验证,导致可以任意文件下载。

    正常的图片显示:

    

进行绕过下载显示文件内容:

    

未深入利用,这里的修复方案有两种1.黑名单验证修复 2.白名单验证修复

    这里我选择2的修复方案。

    谈修复方案之前先讲解下何为黑名单,何为黑名单!

      黑名单就是决定阻止的内容,比如我想要过滤一些特殊的字符,如果我的列表中存在这些特殊字符就拦截他们,这种属于黑名单

      白名单就是决定放行的内容,比如我允许你输入a-z,如果用户输入的内容范围不在a-z以内,我就认为你的行为是非法的,这种属于白名单。

          各自的优缺点:白名单比黑名单更安全,白名单不利于用户体验,为了用户体验大多数企业还是选择黑名单,黑名单容易被绕过!

          这里的修复思路:允许用户下载的文件在我的某个列表中,如果用户下载的内容不在我的文件列表中,那么我认为你的行为是非法的!

          具体修复代码如下:

             首先如果需要下载的文件不存在那么将会302跳转到ErrorInfo.html页面,代码如下:

             

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
未找到文件!请重试...
</body>
</html>

      java部分文件下载实现代码:

         

package cn.downloadServlet;

import java.io.*;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Base64; import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.ws.RespectBinding; import com.sun.org.apache.xerces.internal.util.SynchronizedSymbolTable;
import com.sun.xml.internal.bind.v2.runtime.output.StAXExStreamWriterOutput; import sun.misc.BASE64Encoder; public class DownloadServlet2 extends HttpServlet {
static String[] arr =null;
//获取文件夹下所有文件名称
public static void getFileName() {
String path = "D:\\JavaWeb\\.metadata\\.plugins\\org.eclipse.wst.server.core\\tmp2\\wtpwebapps\\WEB14\\download";
File f = new File(path);
ArrayList<String> arrayList=new ArrayList<>();
if (!f.exists()) {
System.out.println(path + " not exists");
return;
}
File fa[] = f.listFiles();
for (int i = 0; i < fa.length; i++) {
File fs = fa[i];
if (fs.isDirectory()) {
arrayList.add(fs.getName());
} else {
arrayList.add(fs.getName());
}
}
arr= new String[arrayList.size()];
for (int i = 0; i <arr.length; i++) {
arr[i]=arrayList.get(i);
}
} public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 请求filename参数
String filename = request.getParameter("filename");
// System.out.println(filename);
// 解决获得中文参数的乱码
filename = new String(filename.getBytes("ISO8859-1"), "UTF-8");
// 获得请求头中的User-Agent
String agent = request.getHeader("User-Agent");
// 根据不同浏览器进行不同的编码
String filenameEncoder = "";
if (agent.contains("MSIE")) {
// IE浏览器
filenameEncoder = URLEncoder.encode(filename, "utf-8");
filenameEncoder = filenameEncoder.replace("+", " ");
} else if (agent.contains("Firefox")) {
// 火狐浏览器
BASE64Encoder base64Encoder = new BASE64Encoder();
filenameEncoder = "=?utf-8?B?" + base64Encoder.encode(filename.getBytes ("utf-8")) + "?=";
} else {
// 其它浏览器
filenameEncoder = URLEncoder.encode(filename, "utf-8");
}
getFileName();
String requestURI = request.getRequestURI();
System.out.println(requestURI);
// 自动判断文件的数据类型
response.setContentType(this.getServletContext().getMimeType(filename));
// 告诉客户端该文件不是直接解析 而是以附件形式打开(下载)
response.setHeader("Content-Disposition", "attachment;filename=" + filenameEncoder);
//获取请求的文件路径名称
String realPath = this.getServletContext().getRealPath("/download/" + filename);
boolean key = false;
//函数调用
getFileName();
String arrs=null;
for (int i = 0; i < arr.length; i++) {
arrs=arr[i];
//文件判断
if (arrs.equals(filename)) {
key = true;
}
} if (key == true) {
ServletOutputStream outputStream = response.getOutputStream();
FileInputStream fileInputStream = new FileInputStream(realPath);
int length = 0;
byte[] buff = new byte[1024];
while ((length = fileInputStream.read(buff)) != -1) {
outputStream.write(buff, 0, length);
}
} else {
response.sendRedirect("/WEB14/ErrorInfo.html");
}
} public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}

    我们再次实验下是否存在文件下载漏洞了。

      正常的图片下载:

    

尝试读取其他文件内容:

    

说明我们利用这种方法是可以有效防止文件下载漏洞的!

    不忘初心,方得始终。

 

      

												

从Java的角度修复文件下载漏洞的更多相关文章

  1. 从Java的角度修复CSRF漏洞

    漏洞挖掘中,说实话挖过最多的漏洞就属CSRF漏洞了,提交CSRF漏洞很多次,绕过CSRF防御进行攻击也有很多次.CSRF漏洞是一个很容易引发的问题,今天我从Java的角度来说下这个安全漏洞的修复方案. ...

  2. 【代码审计】XYHCMS V3.5任意文件下载漏洞分析

      0x00 环境准备 XYHCMS官网:http://www.xyhcms.com/ 网站源码版本:XYHCMS V3.5(2017-12-04 更新) 程序源码下载:http://www.xyhc ...

  3. 【代码审计】ThinkSNS_V4 任意文件下载漏洞分析

      0x00 环境准备 ThinkSNS官网:http://www.thinksns.com 网站源码版本:ThinkSNS V4  更新时间:2017-09-13 程序源码下载:http://www ...

  4. 【代码审计】EasySNS_V1.6 前台任意文件下载漏洞分析

      0x00 环境准备 EasySNS官网:http://www.imzaker.com/ 网站源码版本:EasySNS极简社区V1.60 程序源码下载:http://es.imzaker.com/i ...

  5. 【代码审计】CLTPHP_v5.5.3后台任意文件下载漏洞分析

      0x00 环境准备 CLTPHP官网:http://www.cltphp.com 网站源码版本:CLTPHP内容管理系统5.5.3版本 程序源码下载:https://gitee.com/chich ...

  6. PHP代码审计笔记--任意文件下载漏洞

    在文件下载操作中,文件名及路径由客户端传入的参数控制,并且未进行有效的过滤,导致用户可恶意下载任意文件.  0x01 客户端下载 常见于系统中存在文件(附件/文档等资源)下载的地方. 漏洞示例代码: ...

  7. ASP代码审计学习笔记 -5.文件下载漏洞

    文件下载漏洞 漏洞代码: <% function download(f,n) on error resume next Set S=CreateObject("Adodb.Stream ...

  8. Java审计之文件操作漏洞

    Java审计之文件操作漏洞篇 0x00 前言 本篇内容打算把Java审计中会遇到的一些文件操作的漏洞,都给叙述一遍.比如一些任意文件上传,文件下载,文件读取,文件删除,这些操作文件的漏洞. 0x01 ...

  9. 从Java的角度理解前端框架,nodejs,reactjs,angularjs,requirejs,seajs

    [前端神秘的面纱] 对后端开发来说,前端是神秘的, 眼花缭乱的技术,繁多的框架, 如果你还停留在前端等于只用jquery做开发,那么你out了, 本文从Java的角度简述下目前前端流行的一些框架. 水 ...

随机推荐

  1. hadoop的缺点

    Hadoop的限制 Hadoop只能执行批量处理,并且只以顺序方式访问数据.这意味着必须搜索整个数据集,即使是最简单的搜索工作.

  2. python爬虫之scrapy的pipeline的使用

    scrapy的pipeline是一个非常重要的模块,主要作用是将return的items写入到数据库.文件等持久化模块,下面我们就简单的了解一下pipelines的用法. 案例一: items池 cl ...

  3. 协程和异步io

    一. 并发.并行.同步.异步.阻塞.非阻塞 1.并发:是指一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都是在同一个处理机(CPU)上运行,但任一个时刻点上只有一个程序在处理机上运 ...

  4. Spring Boot基础:Spring Boot简介与快速搭建(1)

    1. Spring Boot简介 Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化Spring应用的创建.运行.调试.部署等. Spring Boot默认使用tomca ...

  5. 日志与python日志组件logging

    1. 日志的相关概念: (1)日志的作用: a. 开发人员进行程序调试 b. 开发人员定位程序故障的位置 c. 运维人员观察应用运行是否正常 (2)日志的等级 a. DEBUG 最详细的日志,用于问题 ...

  6. thinkphp5 实现搜索分页能下一页保留搜索条件

    正常情况下: 搜索后分页了,点击第二页,进入页面之前的搜索条件没有了. 如代码 $keywords=$this->request->param('keywords'); $this-> ...

  7. C-LODOP设置同一页面 手机电脑都打印

    C-Lodop有四种角色,1:客户端本地打印方式客户端访问web,调用客户端本地的打印机进行打印,这时候调用的安装在客户端本地的c-lodop服务,实际调用的是http://Localhost:800 ...

  8. react使用setstate注意的两点

    1.this.state里的属性不修改,或是只修改一个,那么不修改的剩下的属性不会被变动. this.state={ name:"Aliece", age:19, msg:&quo ...

  9. bzoj2152-[国家集训队]聪聪可可

    Description 聪聪和可可是兄弟俩,他们俩经常为了一些琐事打起来,例如家中只剩下最后一根冰棍而两人都想吃.两个人都想玩儿电脑(可是他们家只有一台电脑)--遇到这种问题,一般情况下石头剪刀布就好 ...

  10. node.js 高级功能

    一.Web 模块 1.http 请求(client.js) var http = require('http'); // 用于请求的选项 var options = { host: 'localhos ...