Advisories

Windows Media Foundation Type Confusion Vulnerability

CVE ID

CVE-2021-34503

Tested Versions

  • mfsrcsnk.dll 10.0.18362.836

Description of the vulnerability

There is a type confusion when parsing Quick Time video file format’s metadata that leads to OOB access on heap memory. The vulnerability can be triggered by navigating into folder contains POC file, inside Internet Explorer and Microsoft Edge.

Technical Details

The crashes happens inside mfmp4srcsnk.dll when parsing CQTSampleDescriptionAtom. Stack trace.

(2154.3bf0): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=05d90ee8 ebx=05d7ef00 ecx=05d84f78 edx=05d8efe8 esi=5ba00cf0 edi=05d80f00
eip=5ba43c64 esp=006fedec ebp=006fedf8 iopl=0         nv up ei pl zr na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00010246
mfmp4srcsnk!CAVCVideoSampleDescription::IsBetterForMediaType+0x44:
5ba43c64 8bb704010000    mov     esi,dword ptr [edi+104h] ds:002b:05d81004=????????
0:000> k
 # ChildEBP RetAddr  
00 006fedf8 5b9fea8a mfmp4srcsnk!CAVCVideoSampleDescription::IsBetterForMediaType+0x44
01 006fee44 5b9fdc50 mfmp4srcsnk!CQTSampleDescriptionAtom::FinalParseAtom+0x36a
02 006feedc 5b9ff7bd mfmp4srcsnk!CQTSampleTable::FinalParseAtom+0x3d0
03 006fef6c 5b9ff51e mfmp4srcsnk!CQTAtom::FinalParseAtom+0xdd
04 006fef8c 5b9ff7bd mfmp4srcsnk!CQTMedia::FinalParseAtom+0x3e
05 006fefd4 5b9fecbc mfmp4srcsnk!CQTAtom::FinalParseAtom+0xdd
06 006ff004 5b9ff7bd mfmp4srcsnk!CQTTrack::FinalParseAtom+0x9c
07 006ff04c 5b9fd1e8 mfmp4srcsnk!CQTAtom::FinalParseAtom+0xdd
08 006ff094 5ba02ed9 mfmp4srcsnk!CQTMovie::FinalParseAtom+0x138
09 006ff0f8 5ba1e00c mfmp4srcsnk!CQTMovie::CreateQTMovie+0x2b9
0a 006ff180 5ba1d4bf mfmp4srcsnk!CQTMovie::CreateMovieFromBuffer+0x571
0b 006ff1b0 5ba252ff mfmp4srcsnk!MFCreateQTMovie+0x4a
0c 006ff1e8 5ba30cea mfmp4srcsnk!CMFMP4PropertyHandler::LoadMetadataProvider+0x13e
0d 006ff25c 5ba351cf mfmp4srcsnk!CMFMP4PropertyHandler::InternalInitialize+0xba
0e 006ff280 753fab92 mfmp4srcsnk!CMFPropHandlerBase::Initialize+0x1af
0f 006ff2d4 75480a38 windows_storage!InitializeFileHandlerWithStream+0x184
10 006ff364 754ef088 windows_storage!CFileSysItemString::HandlerCreateInstance+0x1ba
11 006ff3b4 753fd557 windows_storage!CFileSysItemString::_PropertyHandlerCreateInstance+0x69
12 006ff488 753fb4b6 windows_storage!CFileSysItemString::LoadHandler+0x181
13 006ff748 753fb0cc windows_storage!CFSFolder::LoadHandler+0xa6
14 006ff7a0 753f9849 windows_storage!CFSPropertyStoreFactory::_GetFileStore+0x148
15 006ff7b8 7545a37e windows_storage!CFSPropertyStoreFactory::_s_GetFileStore+0x19
16 006ff828 7545a094 windows_storage!CFSPropertyStoreFactory::_GetMultiplexPropertyStore+0x217
17 006ff86c 7545aa5e windows_storage!CFSPropertyStoreFactory::_GetPropertyStore+0xa9
18 006ff888 7544c632 windows_storage!CFSPropertyStoreFactory::GetPropertyStore+0x1e
19 006ffb7c 7544d5d6 windows_storage!CShellItem::_GetPropertyStoreWorker+0xb22
1a 006ffde4 76887ca6 windows_storage!CShellItem::GetPropertyStore+0xb6
*** WARNING: Unable to verify checksum for metadata.exe
1b 006ffe14 00021085 SHELL32!SHGetPropertyStoreFromParsingName+0x56
1c 006ffe74 00021190 metadata!target_func+0x35 [c:\users\bit\source\repos\mf\metadata\metadata.cpp @ 15] 
1d 006ffe8c 0002137a metadata!wmain+0x40 [c:\users\bit\source\repos\mf\metadata\metadata.cpp @ 55] 
1e (Inline) -------- metadata!invoke_main+0x1c [d:\agent\_work\3\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl @ 90] 
1f 006ffed4 77266359 metadata!__scrt_common_main_seh+0xfa [d:\agent\_work\3\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl @ 288] 
20 006ffee4 77a97c24 KERNEL32!BaseThreadInitThunk+0x19
21 006fff40 77a97bf4 ntdll!__RtlUserThreadStart+0x2f
22 006fff50 00000000 ntdll!_RtlUserThreadStart+0x1b

@edi points to an object of size only 0x100 but the code tries to access a property at offset 0x104.

0:000> !heap -p -a @edi
    address 05d80f00 found in
    _DPH_HEAP_ROOT @ 5cc1000
    in busy allocation (  DPH_HEAP_BLOCK:         UserAddr         UserSize -         VirtAddr         VirtSize)
                                 5cc25b0:          5d80f00              100 -          5d80000             2000
          mfmp4srcsnk!CQTVideoSampleDescription::`vftable'
    5bbfab70 verifier!AVrfDebugPageHeapAllocate+0x00000240
    77b1909b ntdll!RtlDebugAllocateHeap+0x00000039
    77a6bbad ntdll!RtlpAllocateHeap+0x000000ed
    77a6b0cf ntdll!RtlpAllocateHeapInternal+0x0000022f
    77a6ae8e ntdll!RtlAllocateHeap+0x0000003e
    75d97610 msvcrt!malloc+0x00000090
    5ba408cc mfmp4srcsnk!operator new+0x0000001d
    5ba404ef mfmp4srcsnk!CQTVideoSampleDescription::Create+0x0000000a
    5ba04947 mfmp4srcsnk!CQTSampleDescriptionAtom::CreateChildAtom+0x00000247
    5ba0b197 mfmp4srcsnk!CQTAtom::ScanChildrenInBuffer+0x00000077
    5ba0ab4c mfmp4srcsnk!CQTAtom::ScanChildren+0x0000016c
    5ba058a4 mfmp4srcsnk!CQTSampleDescriptionAtom::ParseAtom+0x000001b4
    5ba0af4e mfmp4srcsnk!CQTAtom::CreateTypedAtom+0x0000035e
    5ba0a60e mfmp4srcsnk!CQTSampleTable::CreateChildAtom+0x0000037e
    5ba0b197 mfmp4srcsnk!CQTAtom::ScanChildrenInBuffer+0x00000077
    5ba0ab4c mfmp4srcsnk!CQTAtom::ScanChildren+0x0000016c
    5ba0c4ad mfmp4srcsnk!CQTAtom::ParseAtom+0x000000fd
    5ba0af4e mfmp4srcsnk!CQTAtom::CreateTypedAtom+0x0000035e
    5ba09972 mfmp4srcsnk!CQTMediaInformationAtom::CreateChildAtom+0x000003c2
    5ba0b197 mfmp4srcsnk!CQTAtom::ScanChildrenInBuffer+0x00000077
    5ba0ab4c mfmp4srcsnk!CQTAtom::ScanChildren+0x0000016c
    5ba0c4ad mfmp4srcsnk!CQTAtom::ParseAtom+0x000000fd
    5ba0af4e mfmp4srcsnk!CQTAtom::CreateTypedAtom+0x0000035e
    5ba09204 mfmp4srcsnk!CQTMedia::CreateChildAtom+0x000001e4
    5ba0b197 mfmp4srcsnk!CQTAtom::ScanChildrenInBuffer+0x00000077
    5ba0ab4c mfmp4srcsnk!CQTAtom::ScanChildren+0x0000016c
    5ba0c4ad mfmp4srcsnk!CQTAtom::ParseAtom+0x000000fd
    5ba0af4e mfmp4srcsnk!CQTAtom::CreateTypedAtom+0x0000035e
    5ba08a40 mfmp4srcsnk!CQTTrack::CreateChildAtom+0x00000950
    5ba0b197 mfmp4srcsnk!CQTAtom::ScanChildrenInBuffer+0x00000077
    5ba0ab4c mfmp4srcsnk!CQTAtom::ScanChildren+0x0000016c
    5ba0c4ad mfmp4srcsnk!CQTAtom::ParseAtom+0x000000fd

 
0:000> 
    address 05d80f00 found in
    _DPH_HEAP_ROOT @ 5cc1000
    in busy allocation (  DPH_HEAP_BLOCK:         UserAddr         UserSize -         VirtAddr         VirtSize)
                                 5cc25b0:          5d80f00              100 -          5d80000             2000
          mfmp4srcsnk!CQTVideoSampleDescription::`vftable'
    5bbfab70 verifier!AVrfDebugPageHeapAllocate+0x00000240
    77b1909b ntdll!RtlDebugAllocateHeap+0x00000039
    77a6bbad ntdll!RtlpAllocateHeap+0x000000ed
    77a6b0cf ntdll!RtlpAllocateHeapInternal+0x0000022f
    77a6ae8e ntdll!RtlAllocateHeap+0x0000003e
    75d97610 msvcrt!malloc+0x00000090
    5ba408cc mfmp4srcsnk!operator new+0x0000001d
    5ba404ef mfmp4srcsnk!CQTVideoSampleDescription::Create+0x0000000a
    5ba04947 mfmp4srcsnk!CQTSampleDescriptionAtom::CreateChildAtom+0x00000247
    5ba0b197 mfmp4srcsnk!CQTAtom::ScanChildrenInBuffer+0x00000077
    5ba0ab4c mfmp4srcsnk!CQTAtom::ScanChildren+0x0000016c
    5ba058a4 mfmp4srcsnk!CQTSampleDescriptionAtom::ParseAtom+0x000001b4
    5ba0af4e mfmp4srcsnk!CQTAtom::CreateTypedAtom+0x0000035e
    5ba0a60e mfmp4srcsnk!CQTSampleTable::CreateChildAtom+0x0000037e
    5ba0b197 mfmp4srcsnk!CQTAtom::ScanChildrenInBuffer+0x00000077
    5ba0ab4c mfmp4srcsnk!CQTAtom::ScanChildren+0x0000016c
    5ba0c4ad mfmp4srcsnk!CQTAtom::ParseAtom+0x000000fd
    5ba0af4e mfmp4srcsnk!CQTAtom::CreateTypedAtom+0x0000035e
    5ba09972 mfmp4srcsnk!CQTMediaInformationAtom::CreateChildAtom+0x000003c2
    5ba0b197 mfmp4srcsnk!CQTAtom::ScanChildrenInBuffer+0x00000077
    5ba0ab4c mfmp4srcsnk!CQTAtom::ScanChildren+0x0000016c
    5ba0c4ad mfmp4srcsnk!CQTAtom::ParseAtom+0x000000fd
    5ba0af4e mfmp4srcsnk!CQTAtom::CreateTypedAtom+0x0000035e
    5ba09204 mfmp4srcsnk!CQTMedia::CreateChildAtom+0x000001e4
    5ba0b197 mfmp4srcsnk!CQTAtom::ScanChildrenInBuffer+0x00000077
    5ba0ab4c mfmp4srcsnk!CQTAtom::ScanChildren+0x0000016c
    5ba0c4ad mfmp4srcsnk!CQTAtom::ParseAtom+0x000000fd
    5ba0af4e mfmp4srcsnk!CQTAtom::CreateTypedAtom+0x0000035e
    5ba08a40 mfmp4srcsnk!CQTTrack::CreateChildAtom+0x00000950
    5ba0b197 mfmp4srcsnk!CQTAtom::ScanChildrenInBuffer+0x00000077
    5ba0ab4c mfmp4srcsnk!CQTAtom::ScanChildren+0x0000016c
    5ba0c4ad mfmp4srcsnk!CQTAtom::ParseAtom+0x000000fd

Vulnerability Discovery/Analysis

If there are more than one object the array and CQTSampleDescriptionAtom::CheckIfMultipleSampleEntriesAreAllowed return True iCQTSampleDescriptionAtom::FinalParseAtom will loop through an array of objects and call the vftable’s function at offset 0xb8. CQTSampleDescriptionAtom::CheckIfMultipleSampleEntriesAreAllowed need to check if all object in the array is of the same type but it fails to do so. This lead to a type confusion.

    v1 = CQTAtom::FinalParseAtom((CQTAtom *)this);
    if ( v1 >= 0 )
    {
      v16 = this->length;
      if ( v16 )
      {
        if ( v16 <= 1 || (v1 = CQTSampleDescriptionAtom::CheckIfMultipleSampleEntriesAreAllowed(this), v1 >= 0) )
        {
          this->a38 = 1;
          if ( this->length > 0 )
          {
            while ( 1 )
            {
              wil::details::FeatureImpl<__WilFeatureTraits_Feature_MPEG4MultiSampleDescription>::ReportUsage(
                v26,
                v27,
                v28);
              if ( v4 )
              {
                v19 = (*(int (__thiscall **)(_DWORD, void *, void *))(*(_DWORD *)this->Array[v4] + 0xB8))(
                        *(_DWORD *)(*(_DWORD *)this->Array[v4] + 0xB8),
                        this->Array[v4],
                        this->Array[this->a38 - 1]);
                v4 = v31;
                if ( v19 )
                  this->a38 = v31 + 1;
              }
              v20 = (char *)this->Array[v4] + 12;
              if ( (*(int (__thiscall **)(_DWORD, char *))(*(_DWORD *)v20 + 12))(*(_DWORD *)(*(_DWORD *)v20 + 12), v20) == 'drms' )
                break;
              v4 = v31 + 1;
              v31 = v4;
              if ( v4 >= this->length )
                goto LABEL_57;
            }
            v1 = 0xC00D3700;
            if ( !CallStackTracing::s_wpInstance )
              CallStackTracing::InitInstance();
            if ( *(_BYTE *)(CallStackTracing::s_wpInstance + 4) )
            {
              v21 = CallStackTracing::Context((CallStackTracing *)CallStackTracing::s_wpInstance);
              CallStackContext::SetResult(v21, "CQTSampleDescriptionAtom::FinalParseAtom", 10986, 0xC00D3700);
            }
            if ( g_wppLevels >= 1u )
            {
              v3 = 792;
              goto LABEL_56;
            }
          }
        }

The type confusion occurs due to malformed header related to Protected Sample Entry Box structure.

POC

Original files

The bytes in yellow are related to the crash. The fuzzer mutate encv to ench which causes the crash.

Conclusion

This vulnerability might result in code execution if it is in used with other vulnerabilities.

Timeline

  • 2021-02-27 Reported to Vendor
  • 2021-06-16 Vendor assign CVE

Credit

Discovered by Phan Thanh Duy