Aggregator
Cryptographic Tools for Non-Existence in the Domain Name System: NSEC and NSEC3
This is the second in a multi-part blog series on cryptography and the Domain Name System (DNS). In my previous post, I described the first broad scale deployment of cryptography in the DNS, known as the Domain Name System Security Extensions (DNSSEC). I described how a name server can enable a requester to validate the […]
The post Cryptographic Tools for Non-Existence in the Domain Name System: NSEC and NSEC3 appeared first on Verisign Blog.
深度探索:解除文件占用那些坑
Can Bots Manipulate Data and Change Facts to Fiction?
Top Security Threats to Look Out for in 2021
Top Cyber Security Threats to Look Out for in 2021 2020 was unexpectedly defined by a global pandemic. Throughout the...
The post Top Security Threats to Look Out for in 2021 appeared first on McAfee Blog.
Security Update Guide Supports CVEs Assigned by Industry Partners
Security Update Guide Supports CVEs Assigned by Industry Partners
Internalship Program
The Story Of CVE-2021-1648
Author: k0shl of 360 Vulcan Team
SummaryIn January 2021 patch tuesday, MSRC patched a vulnerability in splwow64 service, assigned to CVE-2021-1648(also known as CVE-2020-17008), which merged my two interesting cases which bypass the patch of CVE-2020-0986, one of them also be found by Google Project Zero((https://bugs.chromium.org/p/project-zero/issues/detail?id=2096).actually this include one EoP and two info leak cases.
This vulnerability was planned to patch in October 2020, but MSRC seems found some other serious security problems in service, so they postpone the patch for four months.
BackgroundIn this blog, I don't want to talk more about the mechanism of splwow64, there are a lot of analysis of CVE-2020-0986 before, so let's focus on the vulnerability.
After CVE-2020-0986 had been patched, I make a quick bindiff on splwow64 and gdi32full, and found there are two check added after patch.
One is that Microsoft added two printer handle(or aka cookie?) check functions named "FindDriverForCookie" and "FindPrinterHandle", it will check printer driver handle which store in a global variable.
__int64 __fastcall FindDriverForCookie(__int64 a1) { v3 = qword_1800EABA0; if ( qword_1800EABA0 ) { do { if ( a1 == *(_QWORD *)(v3 + 56) ) //check driver index break; v3 = *(_QWORD *)(v3 + 8); } while ( v3 ); if ( v3 ) ++*(_DWORD *)(v3 + 44); } RtlLeaveCriticalSection(&semUMPD); return v3;// return driver heap } __int64 *__fastcall FindPrinterHandle(__int64 a1, int a2, int a3) { for ( i = *(__int64 **)(v3 + 64); i && (*((_DWORD *)i + 2) != v5 || *((_DWORD *)i + 3) != v4); i = (__int64 *)*i ) //check printer handle ; }Another is that MSRC added two pointer check functions "UMPDStringPointerFromOffset" and "UMPDPointerFromOffset" to check if pointer is validate.
FindDriverForCookie and FindPrinterHandle bypassFirst, I don't know the purpose that Microsoft add FindDriverForCookie and FindPrinterHandle, maybe it's not for mitigation? After quick review, I found there is a command named 0x6A that can set printer handle which the value we can controll in global variable of service to bypass this two check functions.
__int64 __fastcall bAddPrinterHandle(__int64 a1, int a2, int a3, __int64 a4) { v9 = RtlAllocateHeap(*(_QWORD *)(__readgsqword(0x60u) + 48), 0i64, 24i64); v10 = (_QWORD *)v9; if ( v9 ) { *(_DWORD *)(v9 + 8) = v6; *(_DWORD *)(v9 + 12) = v5; *(_QWORD *)(v9 + 16) = v8; RtlEnterCriticalSection(&semUMPD); *v10 = *(_QWORD *)(v4 + 0x40); v7 = 1; *(_QWORD *)(v4 + 0x40) = v10; //add print handle which can be controlled by user RtlLeaveCriticalSection(&semUMPD); } return v7; }By invoking command 0x6A, function bAddPrinterHandle will add print handle to driver heap which stored in global variable |qword_1800EABA0|.
//set print handle to 0xdeadbeef00006666 0:007> p gdi32full!bAddPrinterHandle+0x54: 00007ff8`380fc3bc 44897808 mov dword ptr [rax+8],r15d ds:00000000`0108a428=00000000 0:007> p gdi32full!bAddPrinterHandle+0x58: 00007ff8`380fc3c0 4489700c mov dword ptr [rax+0Ch],r14d ds:00000000`0108a42c=00000000 0:007> r r14d r14d=deadbeef 0:007> r r15d r15d=6666 //driver heap stored in global variable 0:007> dq gdi32full+0xEABA0 l1 00007ff8`381baba0 00000000`0108d000 0:007> dq 108d000+0x40 l1 00000000`0108d040 00000000`0108a420 0:007> dq 108a420+0x8 l1 00000000`0108a428 deadbeef`00006666So we can easy bypass printer handle check during invoking Command 0x6D, and hit the vulnerability code.
case 0x6Du: v31 = FindDriverForCookie(*(_QWORD *)(v6 + 24)); v32 = v31; if ( !v31 ) goto LABEL_137; v33 = FindPrinterHandle(v31, *(_DWORD *)(v6 + 32), *(_DWORD *)(v6 + 36)); ... [vulnerability code] CVE-2021-1648: arbitrary address readLet's talk about information disclosure, CVE-2020-1648 includes a arbitrary address read information disclosure.
if ( v51 != -1 ) { v57 = **(unsigned __int16 ***)(v6 + 0x50); //not check v57 if ( v57 ) { v58 = v57[34]; v59 = v58 + v57[35]; if ( (unsigned int)v59 >= v58 && (unsigned int)v59 <= 0x1FFFE ) memcpy_0(*(void **)(v6 + 88), v57, v59); //arbitrary address read } }The code of case Command 0x6D is too long, so I won't post all of them in my blog. In short, it will check destination address of memcpy if it's in "validate" range, the range of |v6+0x58|, but source address |v57| isn't checked, so we can read arbitrary address.
0:007> r rax=0000000000868a00 rbx=000000000001fffe rcx=0000000000000000 rdx=4141414141414141 rsi=0000000000150200 rdi=00000000008688d0 rip=00007ff9fc008403 rsp=000000000210f480 rbp=000000000210f4f9 r8=100297f000000002 r9=000000000022f000 r10=00000fff3c9c801d r11=000000000210f350 r12=0000000000868920 r13=0000000000868910 r14=0000000000000001 r15=0000000000461c50 iopl=0 nv up ei pl nz na po nc cs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010206 gdi32full!GdiPrinterThunk+0x1a73: 00007ff9fc008403 0fb74a44 movzx ecx,word ptr [rdx+44h] ds:4141414141414185=????Stack trace:
0:007> k Child-SP RetAddr Call Site 000000000210f480 00007ff7558e78ab gdi32full!GdiPrinterThunk+0x1a73 000000000210f560 00007ff7558e84de splwow64+0x78ab 000000000210f650 00007ff7558e9f28 splwow64+0x84de 000000000210f6b0 00007ff9fe3f2e93 splwow64+0x9f28 000000000210f6e0 00007ff9fe3f45b4 ntdll!RtlDeleteCriticalSection+0x363 000000000210f730 00007ff9fc487bd4 ntdll!RtlInitializeResource+0xce4 000000000210faf0 00007ff9fe42ce51 KERNEL32!BaseThreadInitThunk+0x14 000000000210fb20 0000000000000000 ntdll!RtlUserThreadStart+0x21 Another two cases of CVE-2021-1648Another two cases I reported to MSRC is about bypassing offset check functions "UMPDStringPointerFromOffset" and "UMPDPointerFromOffset", I think MSRC made a mistake in these two functions range check.
Splwow64 is a specail service which is compatible with x86 in x86-64 Windows OS, so it always allocate heap which is 32bits, but in CVE-2020-0986 patch, "UMPDStringPointerFromOffset" and "UMPDPointerFromOffset" only check if offset and |portview+offset| is less than 0x7fffffff.
signed __int64 __fastcall UMPDPointerFromOffset(unsigned __int64 *a1, __int64 a2, unsigned int a3) { [...] if ( v3 <= 0x7FFFFFFF && v3 + a3 <= 0x7FFFFFFF ) { *a1 = v3 + a2; return 1i64; } [...] } signed __int64 __fastcall UMPDStringPointerFromOffset(unsigned __int64 *a1, __int64 a2) { [...] if ( v3 > 0x7FFFFFFF ) goto LABEL_12; v4 = (0x7FFFFFFF - v3) >> 1; *a1 = v3 + a2; v5 = (unsigned int)v4; if ( v3 + a2 ) v2 = wcsnlen((const wchar_t *)(v3 + a2), (unsigned int)v4); [...] return result; }But in splwow64 service, so many heaps even stack is allocated in low address, like this:
0:004> pc splwow64!TLPCMgr::ProcessRequest+0x99: 00007ff6`846d7c71 e826490000 call splwow64!operator new[] (00007ff6`846dc59c) 0:004> p splwow64!TLPCMgr::ProcessRequest+0x9e: 00007ff6`846d7c76 488bf0 mov rsi,rax 0:004> r rax rax=00000000007d7c70 0:004> r rsp rsp=000000000217f400So it is possible to exploit through occupy to some important heaps or stack in splwow64 service, I suggest MSRC in my report to check range of pointer if it's in portview section instead of 0x7fffffff.
two cases crash dump:
0:006> r rax=0000000000000000 rbx=00000000012f8360 rcx=000000001363d9e0 rdx=00000000012f8360 rsi=0000000002d60200 rdi=000000001363d9d8 rip=00007fff728956d2 rsp=0000000002cdf230 rbp=0000000000000001 r8=0000000000000028 r9=0000000012345678 r10=000000007fffffff r11=2222222222222222 r12=00007fff57ea8fe0 r13=0000000001208210 r14=000000000120aa50 r15=00007fff72860000 iopl=0 nv up ei pl nz na po nc cs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010206 gdi32full!UMPDStringPointerFromOffset+0x12: 00007fff728956d2 4c8b09 mov r9,qword ptr [rcx] ds:000000001363d9e0=???????????????? 0:006> r rax=0000000000000001 rbx=0000000001628360 rcx=0000000042a3c4a1 rdx=0000000001628360 rsi=0000000000ff0200 rdi=0000000000000000 rip=00007fff7289568a rsp=0000000002ecf3d8 rbp=0000000000000001 r8=0000000000000028 r9=0000000041414141 r10=000000007fffffff r11=2222222222222222 r12=00007fff57ea8fe0 r13=0000000001407160 r14=000000000140a000 r15=00007fff72860000 iopl=0 nv up ei pl nz na po nc cs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010206 gdi32full!UMPDPointerFromOffset+0xa: 00007fff7289568a 4c8b09 mov r9,qword ptr [rcx] ds:0000000042a3c4a1=???????????????? The end of storyIt seems Microsoft redsigned splwow64 printer service, so they postponed the patch for four months, it's really a long time for me to wait a patch since I started my researching on Windows. Hope new printer service will be more secure:P.
Timeline
2020-07-27 Reported to MSRC.
2020-08-19 MSRC decided to put off patch.
2020-08-22 Bounty awarded
2021-01-13 Patch release