加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

JAVA读写文件可能的漏洞

(2017-11-16 20:35:56)
标签:

安全性

文件

分类: JAVA

BY_JSC_JOHOLE

 前端通过自定义文件名字做成能任意下载文件的漏洞。将HTTP请求中的filename参数作为待下载的文件名,从而在指定目录里寻找指定文件响应下载请求返回文件。具体原理如下:


protected void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException {
    String rootPath = this.getServletContext().getRealPath("/");
    String filename = request.getParameter("filename");
    if (filename == null)
        filename = "";
    filename = filename.trim();
    InputStream inStream = null;
    byte[] b = new byte[1024];
    int len = 0;
    try {
        if (filename == null) {
            return;
        }
        //
读到流中
        //
本行代码未对文件名参数进行过滤,存在任意文件下载漏洞
        inStream = new FileInputStream(rootPath + "/download/" + filename);
        //
设置输出的格式
        response.reset();
        response.setContentType("application/x-msdownload");
        response.addHeader("Content-Disposition", "attachment; filename=\""
                + filename + "\"");
        //
循环取出流中的数据
        while ((len = inStream.read(b)) > 0) {
            response.getOutputStream().write(b, 0, len);
        }
        response.getOutputStream().close();
        inStream.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

通常对于下载文件的请求都没有对http请求的文件做复核,前端甚至可以在自定义的文件名里写上任意的路径达到在下载指定路径里的指定文件的目的。

java.io.File对象有两个方法可以用于获取文件对象的路径,getAbsolutePathgetCanonicalPath。这里用getCanonicalPath做例子,在JDKgetCanonicalPath的说明是:返回此抽象路径名的规范路径名字符串。

规范路径名是绝对路径名,并且是惟一的。规范路径名的准确定义与系统有关。如有必要,此方法首先将路径名转换为绝对路径名,这与调用 getAbsolutePath() 方法的效果一样,然后用与系统相关的方式将它映射到其惟一路径名。这通常涉及到从路径名中移除多余的名称(比如 "." "..")、解析符号连接(对于 UNIX 平台),以及将驱动器号转换为标准大小写形式(对于 Microsoft Windows 平台)。每个表示现存文件或目录的路径名都有一个惟一的规范形式。每个表示不存在文件或目录的路径名也有一个惟一的规范形式。不存在文件或目录路径名的规范形式可能不同于创建文件或目录之后同一路径名的规范形式。同样,现存文件或目录路径名的规范形式可能不同于删除文件或目录之后同一路径名的规范形式。试着在windows中测试getCanonicalPath

public static void main(String[] args) {
             getFilePath("C:/Windows/System32/calc.exe");


                          getFilePath("C:/Windows/System32/drivers/etc/../../notepad.exe");
 }

private static void getFilePath(String filename) {
    File f = new File(filename);
    try {
        System.out.println("getCanonicalPath: " + filename + f.getCanonicalPath());
    } catch (Exception e) {
        e.printStackTrace();
    }
}

输出的结果是:


getCanonicalPath: C:/Windows/System32/calc.exeC:\Windows\System32\calc.exe
getCanonicalPath: **C:/Windows/System32/drivers/etc/../../notepad.exeC:\Windows\System32\notepad.exe**

windows..代表的是上一层目录,如果传来的名字里包含了类似符号,java会按照相应的规范对..做读取上一层目录的操作,这就导致了能任意读取指定路径指定文件的漏洞。

防范这类漏洞的方法:

         在生成File文件类之前,对http的请求下载路径进行复核,如果路径不是能允许下载的路径则返回空或者拒绝下载请求。

         不从http请求中获取名字加入下载路径,把可供下载文件的路径和名字存储在数据库中。当接受到下载请求的时候,获取http请求中传来的文件名,在数据库中查找文件路径再生成File文件类进行读取。

以上两种方法各有优缺。第一种方法在存放文件的时候需要提前定义一个不变文件路径,且所有的文件都只能存放在这个文件路径里,如果需要分类则必须提前分类好文件夹路径。如果文件路径需要更改,需要改动的地方较多,并且对程序的维护不利。但是能杜绝大多数的非法路径请求,而且响应下载的速度较快。第二种方法因为要先建立通道查询数据库中的信息所以对请求的响应较慢,并且要确保数据库中的记录不被删改或者丢失。优点是文件可以随时自定义分类存放在各个路径中,方便维护,并且确保数据中的数据正确的情况下对文件的保护的安全系数较高。

 参考出处:乌云网

如需沟通讨论,可联系QQ2622487640,本文版权归智扬信达所有,转载请注明出处

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有