Talos Vulnerability Report

TALOS-2023-1730

Microsoft Office Excel FreePhisxdb arbitrary free vulnerability

June 13, 2023
CVE Number

CVE-2023-32029

SUMMARY

An arbitrary free vulnerability exists in the FreePhisxdb functionality of Microsoft Office Excel 2019 Plus 16.0.16130.20218. A specially-crafted malformed file can lead to an arbitrary free. An attacker can provide a malicious file to trigger this vulnerability.

CONFIRMED VULNERABLE VERSIONS

The versions below were either tested or verified to be vulnerable by Talos or confirmed to be vulnerable by the vendor.

Microsoft Office Excel 2019 Plus 16.0.16130.20218

PRODUCT URLS

Office - https://products.office.com

CVSSv3 SCORE

7.8 - CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H

CWE

CWE-763 - Release of Invalid Pointer or Reference

DETAILS

Microsoft Office is a suite of tools used for productivity in both a corporate environment as well as by end-users. It offers a range of tools that can be used for various purposes. Such as Excel for spreadsheets, Word for document editing, Outlook for email, PowerPoint for presentations, etc.

Running Excel with our testcase, with PageHeap turned on, we can observe the following crash information in windbg :

First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=491a1000 ebx=5e196619 ecx=00000000 edx=543bafe0 esi=491a1c80 edi=543bafe8
eip=013e919d esp=034def50 ebp=034def6c iopl=0         nv up ei ng nz na po cy
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00210283
Excel!FreePhisxdb+0x9e:
013e919d 8b08            mov     ecx,dword ptr [eax]  ds:002b:491a1000=????????
0:000> kb
 # ChildEBP RetAddr  Args to Child              
00 034def6c 013e8f8a 45cd6fc8 034df288 05df6fd8 Excel!FreePhisxdb+0x9e
01 034def88 005a5b73 034df288 05df6fd8 800a09c4 Excel!FreeHisxInfo+0x141
02 034df068 006e0244 034df1f0 00000000 05df6fd8 Excel!FSetupLoadHtmlPass+0x585
03 034df198 013acc1f 00000100 4b29cfa8 00000003 Excel!HrLoadSheetHtml+0x557
04 034e9afc 01c197de 00000000 00000000 00000000 Excel!HrBookLoadHtmlSinglePly+0x4c2
05 034e9b40 002a1fc6 034f91d8 4b29cfa8 00000002 Excel!HrLoadBookHtml+0xe4
06 034f960c 002875f6 00000000 00000000 00000002 Excel!HrFileLoadEx+0x6af6
07 034f9698 015c90ec 00000000 00000000 00000002 Excel!FFileLoadWithCoauth+0x72
08 034f96ec 011a29be 00000000 02823042 034f9714 Excel!FFileLoadWithCoauth+0x45
09 034f97e8 011a2723 00000001 00001008 00000001 Excel!_HrLoadInternal+0x193
0a 034f9890 000aebde 00000001 00001008 00000001 Excel!_HrLoad+0xd1
0b 034fe5e8 000ad337 0000000f 4c6c6fb0 00000825 Excel!FStartupFilename+0x1970
0c 034fe68c 01f54e82 0000000f 4c6c6fb0 00000825 Excel!FLoadCmdLine+0x99
0d 034ff204 001018c3 00000825 00000000 00000001 Excel!MergeInstance::ExecuteMergeInstance+0xdd
0e 034ff2b0 000f605c 05df6fd8 05df6fd8 00000000 Excel!DelayedMergeInstance::FProcessRequest+0x110
0f 034ff7d8 000f44a6 05df6fd8 02a0ad08 00000001 Excel!FDoIdleHardRejectUi+0x1c75
10 034ff858 000f082e 5e192f36 02a0aee0 00000000 Excel!FDoIdle+0x9d
11 034ffc58 000855cf 00000000 0000000a 03273000 Excel!MainLoop+0x1335
12 034ffe88 000711c3 00070000 00000000 05e14fd2 Excel!WinMain+0x6fe
13 034ffed4 76a9fa29 03273000 76a9fa10 034fff40 Excel!_imp_load__RmGetList+0x1c7
14 034ffee4 77267a4e 03273000 2725d0aa 00000000 KERNEL32!BaseThreadInitThunk+0x19
15 034fff40 77267a1e ffffffff 77288901 00000000 ntdll!__RtlUserThreadStart+0x2f
16 034fff50 00000000 00071079 03273000 00000000 ntdll!_RtlUserThreadStart+0x1b

It seems that there is an attempt to read the data out-of-bounds of some array. Using pseudo-code let us take a closer look at this case:

Line 1     if ( some_edx )
Line 2       external_array = &some_edx->external_array;
Line 3       amount_of_array_dimensions = arg_HISXDB_esi->eax_struct[array_dimensions] // 2
Line 4       external_array_end = (Mso::Memory **)&some_edx->external_array + some_edx->word_size_x * some_edx->word_size_y);// 4 * 1
Line 5       if ( &some_edx->external_array < external_array_end ) 
Line 6       {
Line 7         internal_array_size = 0xc80 * amount_of_array_dimensions;//  4 bytes elements size * 800 elements * 2 dimensions
Line 8         do
Line 9         {
Line 10          Mso::Memory *internal_array = *external_array;
Line 11          internal_array_end = internal_array + internal_array_size;          
Line 12          if ( internal_array < internal_array_end )
Line 13          {            
Line 14            do
Line 15            {
Line 16              if ( *internal_array )
Line 17              {
Line 18                Mso::Memory::Free(*internal_array); //free element
Line 19              }
Line 20              internal_array = internal_array + 4; //increase by element size (pointer)
Line 21            }
Line 22            while ( internal_array < internal_array_end );
Line 23          }
Line 24          Mso::Memory::Free(*external_array);          
Line 25          ++external_array;
Line 26        }
Line 27        while ( external_array < external_array_end );// sizeof(external_array) == 1

Out-of-bounds read appears in line 16 where there is a check on whether the array’s element is different than 0. A while loop in lines 14-22 is controlled by the internal_array_end variable calculated indirectly in line 7. The value of amount_of_array_dimensions is equal to 2, but when we check allocated size for internal_array :

0:000> !heap -p  -a 491a1000-1
    address 491a0fff found in
    _DPH_HEAP_ROOT @ 5dc1000
    in busy allocation (  DPH_HEAP_BLOCK:         UserAddr         UserSize -         VirtAddr         VirtSize)
                                3d931548:         491a0380              c80 -         491a0000             2000
    5fd4a8b0 verifier!AVrfDebugPageHeapAllocate+0x00000240
    772def3e ntdll!RtlDebugAllocateHeap+0x00000039
    77247080 ntdll!RtlpAllocateHeap+0x000000f0
    77246ddc ntdll!RtlpAllocateHeapInternal+0x0000104c
    77245d7e ntdll!RtlAllocateHeap+0x0000003e
    5e18bd4e mso20win32client!Mso::Memory::AllocateEx+0x00000025
    000a1db4 Excel!HrAllocPvClearSafeOBSOLETE+0x000000c0
    01c3c08a Excel!HrAllocPvClearOBSOLETE+0x0000001b
    013ed95a Excel!HrCommitHtmlPivotTables+0x000004d3
    013eb3b1 Excel!HrCollectHtmlPivotCacheRecordset+0x00000059
    013addf8 Excel!HrCollectBookXml+0x000004a3
    01c17b10 Excel!FProcessXmlItem+0x00000a6d
    006e8c58 Excel!OHIU::FProcessXmlItem+0x00000010
    59d9a24e mso!FDispatchXmlItem+0x00000191
    59c84d92 mso!FProcessCloseXmlTag+0x000001c8
    59c81ec8 mso!TkLexHtml+0x000007e8
    59c813de mso!HI::FDoImportCopyContent+0x000001eb
    59c811e0 mso!HI::FDoImport+0x00000019
    006e011e Excel!HrLoadSheetHtml+0x00000425
    013acc1f Excel!HrBookLoadHtmlSinglePly+0x000004c2
    01c197de Excel!HrLoadBookHtml+0x000000e4
    002a1fc6 Excel!HrFileLoadEx+0x00006af6
    002875f6 Excel!FFileLoadWithCoauth+0x00000072
    015c90ec Excel!FFileLoadWithCoauth+0x00000045
    011a29be Excel!_HrLoadInternal+0x00000193
    011a2723 Excel!_HrLoad+0x000000d1
    000aebde Excel!FStartupFilename+0x00001970
    000ad337 Excel!FLoadCmdLine+0x00000099
    01f54e82 Excel!MergeInstance::ExecuteMergeInstance+0x000000dd
    001018c3 Excel!DelayedMergeInstance::FProcessRequest+0x00000110
    000f605c Excel!FDoIdleHardRejectUi+0x00001c75
    000f44a6 Excel!FDoIdle+0x0000009d

it turns out that there is an allocated space just for one element/dimension.

Further investigation revealed that initial PivotCache element parsing resulted in setting amount_of_array_dimensions to 2, according to the amount of Schema elements. Second stage parsing detected a malformed form of one of the Schema elements and did not allocate space for it in the final array/container. All these steps lead in a sequence to out-of-bounds access. It is very important to note here that out-of-bounds read data immediately after check line 16 will be treated as a pointer and passed to Mso::Memory::Free function line 18. With a proper heap grooming, this might lead to arbitrary free and finally to arbitrary code execution.

Crash Information

First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=654f1000 ebx=5e196619 ecx=00000000 edx=16400fe0 esi=654f1c80 edi=16400fe8
eip=013e919d esp=034de938 ebp=034de954 iopl=0         nv up ei ng nz na po cy
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00210283
Excel!FreePhisxdb+0x9e:
013e919d 8b08            mov     ecx,dword ptr [eax]  ds:002b:654f1000=????????
0:000> !analyze -v
*******************************************************************************
*                                                                             *
*                        Exception Analysis                                   *
*                                                                             *
*******************************************************************************


KEY_VALUES_STRING: 1

    Key  : AV.Fault
    Value: Read

    Key  : Analysis.CPU.Sec
    Value: 7

    Key  : Analysis.DebugAnalysisProvider.CPP
    Value: Create: 8007007e on DESKTOP-Q1N26JM

    Key  : Analysis.DebugData
    Value: CreateObject

    Key  : Analysis.DebugModel
    Value: CreateObject

    Key  : Analysis.Elapsed.Sec
    Value: 25

    Key  : Analysis.Memory.CommitPeak.Mb
    Value: 313

    Key  : Analysis.System
    Value: CreateObject

    Key  : Timeline.OS.Boot.DeltaSec
    Value: 453610

    Key  : Timeline.Process.Start.DeltaSec
    Value: 16


NTGLOBALFLAG:  2000000

PROCESS_BAM_CURRENT_THROTTLED: 0

PROCESS_BAM_PREVIOUS_THROTTLED: 0

APPLICATION_VERIFIER_FLAGS:  0

APPLICATION_VERIFIER_LOADED: 1

EXCEPTION_RECORD:  (.exr -1)
ExceptionAddress: 013e919d (Excel!FreePhisxdb+0x0000009e)
   ExceptionCode: c0000005 (Access violation)
  ExceptionFlags: 00000000
NumberParameters: 2
   Parameter[0]: 00000000
   Parameter[1]: 654f1000
Attempt to read from address 654f1000

FAULTING_THREAD:  00001c50

PROCESS_NAME:  Excel.exe

READ_ADDRESS:  654f1000 

ERROR_CODE: (NTSTATUS) 0xc0000005 - The instruction at 0x%p referenced memory at 0x%p. The memory could not be %s.

EXCEPTION_CODE_STR:  c0000005

EXCEPTION_PARAMETER1:  00000000

EXCEPTION_PARAMETER2:  654f1000

STACK_TEXT:  
034de954 013e8f8a 4824efc8 034dec70 06ed6fd8 Excel!FreePhisxdb+0x9e
034de970 005a5b73 034dec70 06ed6fd8 800a03ec Excel!FreeHisxInfo+0x141
034dea50 006e0244 034debd8 00000000 06ed6fd8 Excel!FSetupLoadHtmlPass+0x585
034deb80 013acc1f 00000100 4cdf2fa8 00000003 Excel!HrLoadSheetHtml+0x557
034e94e4 01c197de 00000000 00000000 00000000 Excel!HrBookLoadHtmlSinglePly+0x4c2
034e9528 002a1fc6 034f8bc0 4cdf2fa8 00000002 Excel!HrLoadBookHtml+0xe4
034f8ff4 002875f6 00000000 00000000 00000002 Excel!HrFileLoadEx+0x6af6
034f9080 015c90ec 00000000 00000000 00000002 Excel!FFileLoadWithCoauth+0x72
034f90d4 011a29be 00000000 02823042 034f90fc Excel!FFileLoadWithCoauth+0x45
034f91d0 011a2723 00000001 00001008 00000001 Excel!_HrLoadInternal+0x193
034f9278 000aebde 00000001 00001008 00000001 Excel!_HrLoad+0xd1
034fdfd0 000ad337 0000000f 4a77afb0 00000825 Excel!FStartupFilename+0x1970
034fe074 01f54e82 0000000f 4a77afb0 00000825 Excel!FLoadCmdLine+0x99
034febec 001018c3 00000825 00000000 00000001 Excel!MergeInstance::ExecuteMergeInstance+0xdd
034fec98 000f605c 06ed6fd8 06ed6fd8 00000000 Excel!DelayedMergeInstance::FProcessRequest+0x110
034ff1c0 000f44a6 06ed6fd8 02a0ad08 00000001 Excel!FDoIdleHardRejectUi+0x1c75
034ff240 000f082e 5e192f36 02a0aee0 00000000 Excel!FDoIdle+0x9d
034ff640 000855cf 00000000 0000000a 032c3000 Excel!MainLoop+0x1335
034ff874 000711c3 00070000 00000000 06ef4fb2 Excel!WinMain+0x6fe
034ff8c0 76a9fa29 032c3000 76a9fa10 034ff92c Excel!_imp_load__RmGetList+0x1c7
034ff8d0 77267a4e 032c3000 6009b568 00000000 KERNEL32!BaseThreadInitThunk+0x19
034ff92c 77267a1e ffffffff 7728890e 00000000 ntdll!__RtlUserThreadStart+0x2f
034ff93c 00000000 00071079 032c3000 00000000 ntdll!_RtlUserThreadStart+0x1b


STACK_COMMAND:  ~0s ; .cxr ; kb

SYMBOL_NAME:  Excel!FreePhisxdb+9e

MODULE_NAME: Excel

IMAGE_NAME:  Excel.exe

FAILURE_BUCKET_ID:  INVALID_POINTER_READ_AVRF_c0000005_Excel.exe!FreePhisxdb

OS_VERSION:  10.0.19041.1

BUILDLAB_STR:  vb_release

OSPLATFORM_TYPE:  x86

OSNAME:  Windows 10

FAILURE_ID_HASH:  {0fd87eb4-3286-74ea-9c01-d7830cd32c83}

Followup:     MachineOwner
---------

0:000> lmvm Excel
Browse full module list
start    end        module name
00070000 0316c000   Excel      (pdb symbols)          c:\tools\x86\sym\excel.pdb\A10BA8CB6BAF4234ADCFA6CA7DEBBB5D2\excel.pdb
    Loaded symbol image file: c:\Program Files (x86)\Microsoft Office\root\Office16\EXCEL.EXE
    Image path: Excel.exe
    Image name: Excel.exe
    Browse all global symbols  functions  data
    Timestamp:        Sun Feb 26 04:13:20 2023 (63FB4CE0)
    CheckSum:         030F8001
    ImageSize:        030FC000
    File version:     16.0.16130.20218
    Product version:  16.0.16130.20218
    File flags:       0 (Mask 3F)
    File OS:          40004 NT Win32
    File type:        1.0 App
    File date:        00000000.00000000
    Translations:     0000.04e4
    Information from resource tables:
        CompanyName:      Microsoft Corporation
        ProductName:      Microsoft Office
        InternalName:     Excel
        OriginalFilename: Excel.exe
        ProductVersion:   16.0.16130.20218
        FileVersion:      16.0.16130.20218
        FileDescription:  Microsoft Excel
TIMELINE

2023-03-16 - Vendor Disclosure
2023-06-13 - Vendor Patch Release
2023-06-13 - Public Release

Credit

Discovered by Marcin 'Icewall' Noga of Cisco Talos.