Java 文件或目錄惡意訪問漏洞
本章節將講解與Java文件或目錄訪問安全性問題。常見的Java文件操作相關的漏洞大致有如下類型:
- 任意目錄遍歷
- 任意文件、目錄復制
- 任意文件讀取/下載
- 任意文件、目錄修改/重命名
- 任意文件、目錄刪除
- ……
我們通常把這類漏洞歸為一個類型,因為產生漏洞的原因都是因為程序對文件或目錄訪問控制不嚴、程序內部邏輯錯誤導致的任意文件或目錄惡意訪問漏洞。
Java 任意目錄遍歷漏洞
任意目錄遍歷漏洞顧名思義攻擊者可以通過漏洞遍歷出服務器操作系統中的任意目錄文件名,從而導致服務器敏感信息泄漏,某些場景下(如遍歷出網站日志、備份文件、管理后臺等)甚至可能會導致服務器被非法入侵。
Java 任意目錄遍歷漏洞示例代碼:
<%@ page import="java.io.File" %><%--
Created by IntelliJ IDEA.
User: yz
Date: 2019/12/4
Time: 6:08 下午
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
// 定義需要遍歷的目錄
String dirStr = request.getParameter("dir");
out.println("<h3>" + dirStr + "</h3>");
if (dirStr != null) {
File dir = new File(dirStr);
File[] dirs = dir.listFiles();
out.println("<pre>");
for (File file : dirs) {
out.println(file.getName());
}
out.println("</pre>");
}
%>
當我們通過不斷修改URL中的dir參數即可遍歷出制定目錄的任意文件,漏洞演示URL:http://localhost:8080/file-list.jsp?dir=/Users

這個漏洞可能由Web應用本身的開發不規范導致,也有可能是因為MVC框架、項目依賴的第三方庫、Web服務器自身導致的。如果是由于自身開發不規范導致的那么需要程序嚴格控制用戶傳入目錄參數是否合法!
檢測用戶參數合法性代碼示例(請根據具體業務需求調整判定邏輯):
<%@ page import="java.io.File" %><%--
Created by IntelliJ IDEA.
User: yz
Date: 2019/12/4
Time: 6:08 下午
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%!
// 定義限制用戶遍歷的文件目錄常量
private static final String IMAGE_DIR = "/data/images/";
%>
<%
// 定義需要遍歷的目錄
String dirStr = request.getParameter("dir");
if (dirStr != null) {
File dir = new File(dirStr);
// 獲取文件絕對路徑,轉換成標準的文件路徑
String fileDir = (dir.getAbsoluteFile().getCanonicalFile() + "/").replace("\\\\", "").replaceAll("/+", "/");
out.println("<h3>" + fileDir + "</h3>");
// 檢查當前用戶傳入的目錄是否包含在系統限定的目錄下
if (fileDir.startsWith(IMAGE_DIR)) {
File[] dirs = dir.listFiles();
out.println("<pre>");
for (File file : dirs) {
out.println(file.getName());
}
out.println("</pre>");
} else {
out.println("目錄不合法!");
}
}
%>
請求遍歷非系統限制的目錄示例:

任意文件讀取/編輯/刪除漏洞
任意文件讀寫漏洞即因為沒有驗證請求的資源文件是否合法導致的,此類漏洞在Java中有著較高的幾率出現,任意文件讀取漏洞原理很簡單,但是在這個問題上翻車的有不乏一些知名的中間件:Weblogic、Tomcat、Resin又或者是主流MVC框架:Spring MVC、Struts2。任意文件讀寫、下載的邏輯大致是一致的本節不再一一舉例。
任意文件讀取示例代碼file-read.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="java.io.ByteArrayOutputStream" %>
<%@ page import="java.io.File" %>
<%@ page import="java.io.FileInputStream" %>
<%
File file = new File(request.getParameter("path"));
FileInputStream fis = new FileInputStream(file);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] b = new byte[1024];
int a = -1;
while ((a = fis.read(b)) != -1) {
baos.write(b, 0, a);
}
out.write("<pre>" + new String(baos.toByteArray()) + "</pre>");
fis.close();
%>
任意文件讀取測試:http://localhost:8080/file-read.jsp?path=/etc/passwd

任意文件刪除示例代碼file-delete.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="java.io.File" %>
<%
String fileName = request.getParameter("file");
if (fileName != null) {
// 創建文件對象
File file = new File(fileName);
if (file.exists()) {
file.delete();// 刪除文件
out.println(fileName + "刪除成功!");
} else {
out.println("文件不存在!");
}
}
%>
任意文件刪除測試:http://localhost:8080/file-delete.jsp?file=/tmp/test.txt

任意文件讀/寫/刪除漏洞修復
修改方案主要是嚴格校驗用戶輸入的文件名和目錄是否合法,可參考本節的任意目錄遍歷漏洞修復方式。
Java 惡意文件訪問審計建議
在審計文件讀取功能的時候要非常仔細,或許很容易就會有意想不到的收獲!快速發現這類漏洞得方式其實也是非常簡單的,在IDEA中的項目中重點搜下如下文件讀取的類。
- JDK原始的
java.io.FileInputStream、java.io.FileOutputStream類 - JDK原始的
java.io.RandomAccessFile類 - Apache Commons IO提供的
org.apache.commons.io.FileUtils類 - JDK1.7新增的基于NIO非阻塞異步讀取文件的
java.nio.channels.AsynchronousFileChannel類。 - JDK1.7新增的基于NIO讀取文件的
java.nio.file.Files類。常用方法如:Files.readAllBytes、Files.readAllLines java.io.File類的list、listFiles、listRoots、delete方法。
如果仍沒有什么發現可以搜索一下FileUtil很有可能用戶會封裝文件操作的工具類。
Java 惡意文件訪問總結
首先,在Java中任意文件或目錄惡意訪問漏洞是一種非常常見的高危漏洞!多是因為程序內部邏輯錯誤或者過于信任用戶傳入的參數導致的。其次此類漏洞原理簡單在滲透測試或代碼審計時非常容易發現且漏洞影響重大,因為攻擊者可以直接操縱服務器中的文件或目錄,所以在程序開發過程中我們應該高度重視編碼規范、程序邏輯嚴謹性防止該漏洞發生。
Java Web安全
推薦文章: