Talos Vulnerability Report

TALOS-2016-0023

Apple Quicktime dref Atom Null Data Reference Entry Denial of Service Vulnerability

January 8, 2016

Description

There is a denial of service vulnerability in Apple Quicktime. An attacker who can control the size and type of a data reference entry in a dref atom in a .mov file can cause an undersized allocation which can lead to an out-of-bounds read. Since the allocation only contains data already from the file, the impact is limited to denial of service.

Tested Versions

Apple Quicktime 7.7.5 - Windows 7 32-bit Vulnerable
Apple Quicktime 7.7.6 - Windows 7 32-bit Vulnerable

Product URLs

https://www.apple.com/quicktime/

Details

The function QuickTime!0x73b390 is responsible for parsing dref atoms.

35  while ( sub_6718E000(v3) != 'dref' )
36  {
37    v4 = sub_6718E010(v3);
38    if ( v4 )
39      goto LABEL_19;
40    if ( *(_DWORD *)(v3 + 4) >= v19 )
41    {
42      v4 = -2002;
43      goto LABEL_19;
44    }
45  }

There is some looping code within the function that looks for a dref atom and then processes the data there.

001dbfcc 0000001c  <----- atom size
001dbfd0 64726566  <----- "dref"
001dbfd4 00000000  <----- start of data portion
001dbfd8 00000001  <----- number of entries
001dbfdc 00000000  <--- entry 1 size
001dbfe0 00000000  <--- entry 1 type
001dbfe4 00000000

The data portion of the dref atom is copied into a new allocation. The allocation is the atom size - 0x8 header bytes (size and 4CC) + 0x4 bytes the module’s custom alloc wrapper tacks on.

The following snippet of code runs the dref atom data through a big-to-little-endian function then checks the type and size fields for the data reference entry that follows.

58  dref_be_to_le();
59  if ( dref_type || dref_type_size )
60  {
    (...)
72    goto LABEL_20;
73  }
74  v4 = return_ptr(v3, &dref_data);
75  if ( v4 )
76    goto LABEL_19;
77  v10 = create_tnoc(a3, &a1);
78  v17 = v10;
79  if ( !v10 )
80  {
81    v4 = a1;
82    goto LABEL_18;
83  }
84  v11 = *(_DWORD *)dref_data;
85  v20 = *(_BYTE *)(*(_DWORD *)dref_data + 7) & 1;
86  v12 = sub_6717C120(dref_data);
87  HIBYTE(v13) = *(_BYTE *)(v11 + 24); //Crash
88  LOBYTE(v13) = *(_BYTE *)(v11 + 25); //Crash

If dref_type and dref_type_size are both zero, the code fails the check and execution passes to line 74. If the if-block is taken, it does not reach this line because of the goto at line 72. The crash may occur on line 87 or 88 depending on the size of dref atom data, but the code expects at least 26 bytes without first checking the size of the allocation.

If there is at least 1 data reference entry in a dref atom with a type and size both set to 0, an out-of-bounds read will occur.

Crash Information

eax=00000014 ebx=0023cdf0 ecx=4645142c edx=00000000 esi=00000000 edi=15e00fe8
eip=6a87b2c5 esp=0023c474 ebp=15d5aab0 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00210246
QuickTime!STMediaComponentDispatch+0x3f95:
6a87b2c5 8a7718          mov     dh,byte ptr [edi+18h]      ds:0023:15e01000=??

STACK_TEXT:
0023c4bc 6a88cb4f 00230000 0023c4d8 16b60ef0 QuickTime!STMediaComponentDispatch+0x3f95
0023c4d8 6a251c41 0023cdf0 16b60ef0 0023c554 QuickTime!STMediaComponentDispatch+0x1581f
00000000 00000000 00000000 00000000 00000000 QuickTime!LIST_ComponentDispatch+0x577e1

Credit

Discovered by Ryan Pentney and Richard Johnson of Cisco Talos