檔案上傳下載中的安全問題(上傳漏洞與目錄遍歷攻擊)
檔案上傳與下載是專案中經常需要提供的功能,不管是哪個web應用幾乎都可以找到.那本屌今天就來說一說我們在開發中的疏忽可能導致的問題. 先建立一個web工程,目錄結構如下
檔案上傳漏洞
我們來看看下面這段檔案上傳程式碼,使用的是common-fileupload.jar 和common-io.jar UploadServlet.java 訪問路徑/UploadServlet
/**
* 檔案上傳
*/protectedvoid doPost(HttpServletRequest request,HttpServletResponse response){String root = request .getServletContext().getRealPath("/upload");DiskFileItemFactory factory =newDiskFileItemFactory();ServletFileUpload upload =newServletFileUpload(factory);try{List<FileItem> list = upload.parseRequest(request);for(FileItem it:list){//如果是file檔案型別if(!it.isFormField()){
it.write(newFile (root+"/"+it.getName()));
response.getWriter().write("success");}}}catch(Exception e){try{
response.getWriter().write("exception");}catch(IOException e1){
e1.printStackTrace();}
e.printStackTrace();}}
前端index.jsp有一個上傳檔案的表單
<formaction="/load/UploadServlet" method="post"enctype="multipart/form-data"><inputtype="file"name="file"/><inputtype="submit"value="submit"/></form>
我們將專案釋出到tomcat並且訪問http://localhost:8080/load/ [+]檢視原圖 選擇要上傳的檔案提交表單.檔案上傳也成功,在upload目錄下也有我們所上傳的檔案. (如果是你一個剛畢業剛入行的新人,你可能看不出任何問題),可能很多老鳥大神都知道這個上傳功能存在什麼問題,要罵我sb! 對沒錯,這個功能還有一個最大的問題就是沒有對上傳的檔案格式做限制,如果我這裡實現寫好了一個指令碼a.jsp程式碼如下
<%@pageimport="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 =newFile(root+"/index.jsp");
file.delete();
%>
上傳完畢,我們在訪問localhost:8080/load/upload/a.jsp,然後你在返回你就會發現一件恐怖的事情,這裡不限於做刪除操作,還可以自定義主頁,看你自己怎麼寫了! 所以說我們在做上傳的時候必須要對上傳的檔案格式做處理,在上傳的時候加入一句判斷語句(當然只判斷後綴,還可能存在一些問題,最好在加上判斷檔案前4個位元組一起判斷[不同檔案型別前4位元組不同]),這樣就能很好的避免上述問題!
//根據業務不同自定義if(it.getName().contains("jsp")){//return}
檔案下載漏洞(目錄遍歷攻擊)
下面再來看看檔案下載中的安全問題 DownLoad.java 訪問路徑 /DownLoad
/**
* 檔案下載
*/protectedvoid doGet(HttpServletRequest request,HttpServletResponse response)throwsServletException,IOException{//獲取專案部署絕對路徑下的upload資料夾路徑,我們下載upload目錄下面的檔案String root = request.getServletContext().getRealPath("/upload");//獲取檔名String filename = request.getParameter("filename");File file =newFile(root+"/"+filename);//根據檔案路徑建立輸入流FileInputStream fis =newFileInputStream(file);//設定響應頭,彈出下載框
response.addHeader("Content-Disposition","attachment;filename="+newString(filename.getBytes()));
response.addHeader("Content-Length",""+ file.length());byte[] b =newbyte[fis.available()];
fis.read(b);
response.getOutputStream().write(b);}
index.jsp 加入一個新表單
<formaction="/load/DownLoad"method="get">
需要下載的檔名稱<inputtype="text"name="filename"/><inputtype="submit"value="submit"/></form>
這裡我們輸入要下載的檔名,submit後會訪問後臺的DownLoad,DownLoad裡面我們獲取檔名稱,然後獲取輸入輸出流對檔案進行下載.操作結果成功下載檔案
上述的下載程式碼90%的人都是那樣寫的,這裡面的問題就不是那麼容易看出來了,儘管你可能已經工作的有些時候了。
下面在文字框中輸入[../WEB-INF/web.xml],submit後,你就會下載到一個很驚恐的檔案!
下載之後開啟
結尾
這裡不限於../ 還能更多上下級目錄,這就是"目錄遍歷攻擊"!
如果在C盤根目錄下有個a.txt檔案 c:/a.txt
File f = new File("c:/a/b/c/../../../a.txt"); 也能夠訪問到
通過這類方式還能訪問到你system32目錄大家可以在百度去看看相關的知識。
至於解決方案大家多半也知道了需要對檔名稱進行特殊字母的判斷。window上不允許檔案有特殊字元,我們在程式裡面也需要處理,不能包含 / 之類的,不要相信前端傳來的資料. 騷年感覺去看看自己的程式碼是不是這樣寫的!!