檔案上傳下載中的安全問題(上傳漏洞與目錄遍歷攻擊)

lwphk發表於2015-01-27

前言

檔案上傳與下載是專案中經常需要提供的功能,不管是哪個web應用幾乎都可以找到.那本屌今天就來說一說我們在開發中的疏忽可能導致的問題. 先建立一個web工程,目錄結構如下 enter image description here

檔案上傳漏洞

我們來看看下面這段檔案上傳程式碼,使用的是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/ enter image description here 選擇要上傳的檔案提交表單.檔案上傳也成功,在upload目錄下也有我們所上傳的檔案. (如果是你一個剛畢業剛入行的新人,你可能看不出任何問題),可能很多老鳥大神都知道這個上傳功能存在什麼問題,要罵我sb! 對沒錯,這個功能還有一個最大的問題就是沒有對上傳的檔案格式做限制,如果我這裡實現寫好了一個指令碼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資料夾路徑,我們下載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>

enter image description here

這裡我們輸入要下載的檔名,submit後會訪問後臺的DownLoad,DownLoad裡面我們獲取檔名稱,然後獲取輸入輸出流對檔案進行下載.操作結果成功下載檔案

enter image description here

上述的下載程式碼90%的人都是那樣寫的,這裡面的問題就不是那麼容易看出來了,儘管你可能已經工作的有些時候了。

下面在文字框中輸入[../WEB-INF/web.xml],submit後,你就會下載到一個很驚恐的檔案!

enter image description here

下載之後開啟 enter image description here

結尾

這裡不限於../ 還能更多上下級目錄,這就是"目錄遍歷攻擊"!

如果在C盤根目錄下有個a.txt檔案 c:/a.txt
File f = new File("c:/a/b/c/../../../a.txt"); 也能夠訪問到

通過這類方式還能訪問到你system32目錄大家可以在百度去看看相關的知識。

至於解決方案大家多半也知道了需要對檔名稱進行特殊字母的判斷。window上不允許檔案有特殊字元,我們在程式裡面也需要處理,不能包含 / 之類的,不要相信前端傳來的資料. 騷年感覺去看看自己的程式碼是不是這樣寫的!!

相關文章