
從代碼層面理解java的00截斷漏洞深入篇
4個月前寫了一篇文章叫《從代碼層面理解java的00截斷漏洞》,由于當時出差新疆沒時間深入,便在文末立了個有空繼續(xù)深入的flag。今天我們通過跟蹤jdk代碼,?徹底搞清楚java中00截斷的原理,以及它之后版本是如何修復的?
一、漏洞測試代碼改進
看了一些java web系統(tǒng)文件上傳代碼,基本都是使用FileOutputStream
來實現(xiàn)對上傳內(nèi)容的保存。于是將上篇文章的測試代碼修改如下,簡單模擬java的文件上傳。
import java.io.*; public class T2 { public static void main(String[] args) { String filepath = "c://shell.jsp" + (char)0 + ".txt"; String content = "Test by c0ny1"; System.out.println(filepath); try { FileOutputStream fos = new FileOutputStream(filepath); fos.write(content.getBytes()); fos.close(); } catch (FileNotFoundException e) { e.printStackTrace(); }catch (IOException e) { e.printStackTrace(); } } }
通過在漏洞版本和非漏洞版本運行以上代碼,可知如果00截斷成功,則會在系統(tǒng)的c盤根目錄新建一個內(nèi)容為Test by c0ny1
的shell.jsp
,如果沒有截斷成功,則拋出Invalid file path
異常。
二、漏洞是如何產(chǎn)生的?
我選擇使用JDK1.7.0
(JDK1.7第一個版本),來跟蹤漏洞測試代碼從運行到觸發(fā)。
第一個構(gòu)造函數(shù)
將傳進來的name參數(shù)作為路徑,新建了File對象,再次傳入到FileOutputStream
對象新的構(gòu)造函數(shù)。根據(jù)傳入的兩個參數(shù)的類型,我們可以確定會進入到以下這個構(gòu)造函數(shù)。
第二個構(gòu)造函數(shù)
FileOutputStream對象的構(gòu)造方法又調(diào)用了open函數(shù),打開了name參數(shù)傳進來的文件路徑,我們繼續(xù)跟進open函數(shù)。
open方法的聲明
發(fā)現(xiàn)open函數(shù)是一個native method。它的實現(xiàn)體是由非java語言(c語言)實現(xiàn)的。只能去OpenJDK官網(wǎng)下載jdk源碼來查看它的實現(xiàn)。無奈沒有找到jdk7u1的源碼,只找到了jdk7u75的源碼。其實在小版本上源碼應該區(qū)別不大。
在\openjdk\jdk\src\windows\native\java\io\FileOutputStream_md.c
中找到了FileOutputStream
類的open
方法的JNI實現(xiàn)。open方法又調(diào)用了fileOpen
方法,繼續(xù)跟進fileOpen方法。
open方法的定義
在io_util_md.c
中找到了fileOpen
方法的定義。
fileOpen方法的定義
fileOpen方法調(diào)用了winFileHandleOpen
函數(shù),繼續(xù)跟進。由于winFileHandleOpen函數(shù)代碼比較多,這里精簡出了關(guān)鍵代碼。
jlong winFileHandleOpen(JNIEnv *env, jstring path, int flags) { ...... if (onNT) { //如果在Windows NT/Windows 2000操作系統(tǒng)下 WCHAR *pathbuf = pathToNTPath(env, path, JNI_TRUE); if (pathbuf == NULL) { /* Exception already pending */ return -1; } h = CreateFileW( pathbuf, /* Wide char path name */ access, /* Read and/or write permission */ sharing, /* File sharing flags */ NULL, /* Security attributes */ disposition, /* creation disposition */ flagsAndAttributes, /* flags and attributes */ NULL); free(pathbuf);//創(chuàng)建文件 } else { WITH_PLATFORM_STRING(env, path, _ps) { h = CreateFile(_ps, access, sharing, NULL, disposition,flagsAndAttributes, NULL);//創(chuàng)建文件 } END_PLATFORM_STRING(env, _ps); } ...... return (jlong)h; }
通過閱讀以上代碼,可知如果在Windows NT/Windows 2000平臺下會調(diào)用pathToNTPath
函數(shù)將原始文件路徑轉(zhuǎn)化為Windows NT系統(tǒng)合法路徑。然而通過閱讀該方法源碼,發(fā)現(xiàn)它并沒有對\00字符串進行過濾。如果在其他Window操作系統(tǒng)版本下,則直接使用原始文件路徑。
按照winFileHandleOpen
方法的邏輯,無論如何最終都是調(diào)用了CreateFileW
這個Windows API函數(shù)來創(chuàng)建文件。由于這個過程中均未對\00
字符串進行過濾,如果傳入的文件路徑帶有\(zhòng)00字符,則CreateFileW
函數(shù)在創(chuàng)建文件時,路徑會被截斷。這沒什么好說的。
這里我們沒法繼續(xù)跟進CreateFileW函數(shù),畢竟Windows不開源。為了文章的嚴謹性,這里我用C語言寫一個demo,來證明該函數(shù)可以截斷。
//test.c #include "windows.h" int main() { HANDLE fileHandle = CreateFileW(L"C:\\shell.jsp\0test.txt", GENERIC_WRITE, FILE_SHARE_WRITE, 0, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); char *data = "Test by c0ny1"; DWORD a = strlen(data); unsigned long b; WriteFile(fileHandle, data, a, &b, NULL); CloseHandle(fileHandle); return 0; }
代碼運行演示如下:
CreateFileW函數(shù)00截斷演示
三、漏洞是如何修復的?
這里選擇使用jdk1.7.0_80
(JDK1.7最新版本),來觀察漏洞如果被修復的。
我們繼續(xù)按照原來漏洞觸發(fā)的調(diào)用鏈重新跟蹤一遍,跟蹤到第二構(gòu)造函數(shù)時,發(fā)現(xiàn)多了一個針對文件路徑的檢查,若檢查結(jié)果為非法,則拋出異常Invalid file path
.
構(gòu)造函數(shù)中檢查文件路徑
繼續(xù)跟進,來到java.io.File
類的isInvalid
方法,發(fā)現(xiàn)該檢查函數(shù)判斷了路徑中是否包含00字符串。(注意:java默認編碼為Unicode,00字符串的Unicode編碼為\u0000)。
文件路徑檢查函數(shù)
四、漏洞影響的版本范圍
我們知道jdk1.7版本是部分版本存在漏洞的。但這里我們需要確定是哪個版本修復了這個漏洞。翻閱了JDK1.7多個版本代碼,發(fā)現(xiàn)在JDK1.7.0_40(7u40)開始加上了對文件名是否存在\00字符的檢查。也就是說?JDK1.7.0_40之前java是存在00截斷的,而之后的版本就不存在了!
后面在官網(wǎng)的JDK 7u40的更新日志中也找到了關(guān)于00截斷問題Bug ID,分別為JDK-8003992
和JDK-8011539
,具體鏈接放在了文末的參考文章里了。其實這兩個是同一個Bug,官網(wǎng)也說明了它們重復了。
oracle官方更新日志
五、參考文章
JAVA /00文件路徑截斷漏洞與分析for windows并對.NET比較
JDK-8003992 : File and other classes in java.io do not handle embedded nulls properly
JDK-8011539 : File APIs Should Not Allow Null Bytes
[超站]友情鏈接:
四季很好,只要有你,文娛排行榜:https://www.yaopaiming.com/
關(guān)注數(shù)據(jù)與安全,洞悉企業(yè)級服務市場:https://www.ijiandao.com/

隨時掌握互聯(lián)網(wǎng)精彩
- 1 中美完全可以相互成就、共同繁榮 7904542
- 2 加沙已變“死城” 7808595
- 3 暴雨中臺下只剩1名觀眾 演員仍開演 7713223
- 4 近距離感受“大國重器” 7616117
- 5 美國大豆中國訂單量仍為零 7522558
- 6 試管嬰兒患腎病 父母要求醫(yī)院擔全責 7427441
- 7 女子婚后起訴父母返還18萬彩禮 7333211
- 8 網(wǎng)紅“戶晨風”多平臺賬號被封 7232168
- 9 金價飆升 有非法淘金人井下生活兩年 7142626
- 10 特朗普升級辦公室:肉眼可見全是黃金 7045409