黄色网站入口国产美女,精品国产欧美另类一区,国产一区二区美女自慰,日日摸夜夜添无码国产

選擇你喜歡的標(biāo)簽
我們會(huì)為你匹配適合你的網(wǎng)址導(dǎo)航

    確認(rèn) 跳過

    跳過將刪除所有初始化信息

    從代碼層面理解java的00截?cái)嗦┒瓷钊肫?/h1>
    安全 2021-11-25 05:55

    聲明:該文章來自(回憶如飄雪)版權(quán)由原作者所有,K2OS渲染引擎提供網(wǎng)頁加速服務(wù)。

    4個(gè)月前寫了一篇文章叫《從代碼層面理解java的00截?cái)嗦┒础?/span>,由于當(dāng)時(shí)出差新疆沒時(shí)間深入,便在文末立了個(gè)有空繼續(xù)深入的flag。今天我們通過跟蹤jdk代碼,?徹底搞清楚java中00截?cái)嗟脑恚约八蟀姹臼侨绾涡迯?fù)的?


    一、漏洞測試代碼改進(jìn)

    看了一些java web系統(tǒng)文件上傳代碼,基本都是使用FileOutputStream來實(shí)現(xiàn)對(duì)上傳內(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();
            }
        }
    }
    

    通過在漏洞版本和非漏洞版本運(yùn)行以上代碼,可知如果00截?cái)喑晒?,則會(huì)在系統(tǒng)的c盤根目錄新建一個(gè)內(nèi)容為Test by c0ny1shell.jsp,如果沒有截?cái)喑晒?,則拋出Invalid file path異常。


    二、漏洞是如何產(chǎn)生的?

    我選擇使用JDK1.7.0(JDK1.7第一個(gè)版本),來跟蹤漏洞測試代碼從運(yùn)行到觸發(fā)。

    第一個(gè)構(gòu)造函數(shù)

    將傳進(jìn)來的name參數(shù)作為路徑,新建了File對(duì)象,再次傳入到FileOutputStream對(duì)象新的構(gòu)造函數(shù)。根據(jù)傳入的兩個(gè)參數(shù)的類型,我們可以確定會(huì)進(jìn)入到以下這個(gè)構(gòu)造函數(shù)。

    第二個(gè)構(gòu)造函數(shù)

    FileOutputStream對(duì)象的構(gòu)造方法又調(diào)用了open函數(shù),打開了name參數(shù)傳進(jìn)來的文件路徑,我們繼續(xù)跟進(jìn)open函數(shù)。

    open方法的聲明

    發(fā)現(xiàn)open函數(shù)是一個(gè)native method。它的實(shí)現(xiàn)體是由非java語言(c語言)實(shí)現(xiàn)的。只能去OpenJDK官網(wǎng)下載jdk源碼來查看它的實(shí)現(xiàn)。無奈沒有找到j(luò)dk7u1的源碼,只找到了jdk7u75的源碼。其實(shí)在小版本上源碼應(yīng)該區(qū)別不大。

    \openjdk\jdk\src\windows\native\java\io\FileOutputStream_md.c中找到了FileOutputStream類的open方法的JNI實(shí)現(xiàn)。open方法又調(diào)用了fileOpen方法,繼續(xù)跟進(jìn)fileOpen方法。

    open方法的定義

    io_util_md.c中找到了fileOpen方法的定義。

    fileOpen方法的定義

    fileOpen方法調(diào)用了winFileHandleOpen函數(shù),繼續(xù)跟進(jìn)。由于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平臺(tái)下會(huì)調(diào)用pathToNTPath函數(shù)將原始文件路徑轉(zhuǎn)化為Windows NT系統(tǒng)合法路徑。然而通過閱讀該方法源碼,發(fā)現(xiàn)它并沒有對(duì)\00字符串進(jìn)行過濾。如果在其他Window操作系統(tǒng)版本下,則直接使用原始文件路徑。

    按照winFileHandleOpen方法的邏輯,無論如何最終都是調(diào)用了CreateFileW這個(gè)Windows API函數(shù)來創(chuàng)建文件。由于這個(gè)過程中均未對(duì)\00字符串進(jìn)行過濾,如果傳入的文件路徑帶有\(zhòng)00字符,則CreateFileW函數(shù)在創(chuàng)建文件時(shí),路徑會(huì)被截?cái)?。這沒什么好說的。

    這里我們沒法繼續(xù)跟進(jìn)CreateFileW函數(shù),畢竟Windows不開源。為了文章的嚴(yán)謹(jǐn)性,這里我用C語言寫一個(gè)demo,來證明該函數(shù)可以截?cái)唷?/p>

    //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;
    }
    

    代碼運(yùn)行演示如下:

    CreateFileW函數(shù)00截?cái)嘌菔?></a></p><p>CreateFileW函數(shù)00截?cái)嘌菔?/p><p><br></p><h2><strong>三、漏洞是如何修復(fù)的?</strong></h2><p>這里選擇使用<code>jdk1.7.0_80</code>(JDK1.7最新版本),來觀察漏洞如果被修復(fù)的。</p><p>我們繼續(xù)按照原來漏洞觸發(fā)的調(diào)用鏈重新跟蹤一遍,跟蹤到第二構(gòu)造函數(shù)時(shí),發(fā)現(xiàn)多了一個(gè)針對(duì)文件路徑的檢查,若檢查結(jié)果為非法,則拋出異常<code>Invalid file path</code>.</p><p><img src=

    構(gòu)造函數(shù)中檢查文件路徑

    繼續(xù)跟進(jìn),來到java.io.File類的isInvalid方法,發(fā)現(xiàn)該檢查函數(shù)判斷了路徑中是否包含00字符串。(注意:java默認(rèn)編碼為Unicode,00字符串的Unicode編碼為\u0000)。

    文件路徑檢查函數(shù)


    四、漏洞影響的版本范圍

    我們知道jdk1.7版本是部分版本存在漏洞的。但這里我們需要確定是哪個(gè)版本修復(fù)了這個(gè)漏洞。翻閱了JDK1.7多個(gè)版本代碼,發(fā)現(xiàn)在JDK1.7.0_40(7u40)開始加上了對(duì)文件名是否存在\00字符的檢查。也就是說?JDK1.7.0_40之前java是存在00截?cái)嗟?,而之后的版本就不存在了?/strong>

    后面在官網(wǎng)的JDK 7u40的更新日志中也找到了關(guān)于00截?cái)鄦栴}Bug ID,分別為JDK-8003992JDK-8011539,具體鏈接放在了文末的參考文章里了。其實(shí)這兩個(gè)是同一個(gè)Bug,官網(wǎng)也說明了它們重復(fù)了。

    oracle官方更新日志


    五、參考文章

    JAVA /00文件路徑截?cái)嗦┒磁c分析for windows并對(duì).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


    關(guān)注我們

    [超站]友情鏈接:

    四季很好,只要有你,文娛排行榜:https://www.yaopaiming.com/
    關(guān)注數(shù)據(jù)與安全,洞悉企業(yè)級(jí)服務(wù)市場:https://www.ijiandao.com/

    圖庫