Talos Vulnerability Report

TALOS-2015-0018

Apple Quicktime Corrupt stbl Atom Remote Code Execution Vulnerability

Jun 30, 2015

Description

There is a remote code execution vulnerability in Apple Quicktime. An attacker who can control the data inside an stbl atom in a .mov file can cause an undersized allocation which can lead to an out-of-bounds read. An attacker can use this to create a use-after-free scenario that could lead to remote code execution.

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 QuickTimeMPEG4!0x147f0 is responsible for processing the data in an hdlr atom.

A 16-byte memory region is allocated near the beginning of the function.

		
28  object_ref = AllocWrap(16, &v13); // returns allocation of size 16
		
		

If the hdlr subtype field in an mdia atom is set to 'vide', this reference is passed to a set of two functions. The first function swaps out the reference in object_ref for a bigger object, one of size 0xb0 bytes and the second function operates on this new object.


42      Determine_4CC(v5, &The_4CC_from_obj, 0, 0);
43      switch ( The_4CC_from_obj )
44      {
45        case 'odsm':
46        case 'sdsm':
47          sub_6A8A9FB0(v4, &v20, &v22, &v16, &v21);
48          v16 |= 1u;
49          v20 = -1;
50          sub_6A8A9F90(v4, -1, v22, v16, v21);
51          break;
52        case 'hint':
53          sub_6A8A9E90(v4, 0);
54          break;
55        case 'vide':
56          sub_6A8A9F10(v5, 1, object_ref);  <- Back-to-back function calls
57          if ( (unsigned __int8)sub_6A894F10() )  <----Back-to-back function calls
58          {
59            v6 = sub_6A8AA190(v4, 'visu', 'cldi', 8, &v23, 0);
		
		

At some point up the call stack for the first of these two functions, the reference in question is passed to the function QuickTime!0x73e0f0. However, when the stbl atom is missing from the file (or the 4CC is corrupted) the object at eax does not get populated. When this happens, the check at line 15 will pass and an error code (0xfffff809) will be passed back down the call stack.


7   v3 = *(_DWORD *)(a1 + 66);
(...)
12  else if ( v3 )
13  {
14    v5 = *(_DWORD *)v3;
15    if ( a2 < 1 || a2 > *(_DWORD *)(v5 + 76) ) <---object+0x4c
16    {
17      result = 0xFFFFF809;
18    }
19    else
20    {
21      *(_DWORD *)ptr_to_args = *(_DWORD *)(**(_DWORD **)(v5 + 168) + 4 * a2);
22      result = 0;
23    }
24  }
		
		

This series of calls would normally lead to the replacement of the object reference lie in the function QuickTime!0x748a40. However, because the error code returned down the stack isn't zero, the branch below is taken and the code path skipped.


9    LOWORD(result) = sub_67183760(*(_DWORD *)(a1 + 4), a2, &a1);
10   if ( (_WORD)result )    <----------- result not zero
11   {
12     result = (signed __int16)result;
13   }
14   else
15   {
16     v4 = sub_6717C2C0(a1, 0);
17     v5 = ptr_to_tiny;
18     v6 = v4;
19     v7 = sub_6717C2B0(ptr_to_tiny, v4);
20     if ( !v7 )
21       to_memcpy(*(_DWORD *)a1, *(_DWORD *)v5, v6);
22     result = v7;
23   }
24   return result;
		
		

Eventually, the calls return and the function at line 57 of QuickTimeMPEG4!0x147f0 is called.


56          sub_6A8A9F10(v5, 1, object_ref);  <- Back-to-back function calls
57          if ( (unsigned __int8)sub_6A894F10() )  <-Back-to-back function calls
		
		

Code execution makes its way up to the function QuickTime!0x21ab00.


11  v3 = *(_DWORD *)small_object;
12  result = 86;
13  if ( !*(_WORD *)(*(_DWORD *)small_object + 84) )
14    result = 8 * *(_WORD *)(v3 + 92) + 102;
		
		

A read of 2 bytes is attempted at an offset of 84 bytes into the 16-byte object, resulting in an out-of-bounds read.

Crash Information


eax=03454fa8 ebx=1bceadbc ecx=1bceadbc edx=0000000c esi=1898ffe8 edi=002bc370
eip=6a35a778 esp=002bc358 ebp=002bc3b0 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00210206
QuickTime!LIST_ComponentDispatch+0x160318:
6a35a778 66837e5400      cmp     word ptr [esi+54h],0     ds:0023:1899003c=????


STACK_TEXT:
002bc3b0 6a35a9ea 1bceadbc 70617370 00000001 QuickTime!LIST_ComponentDispatch+0x160318
002bc440 68b84f2e 1bceac9e 1bceadbc 00005d98 QuickTime!LIST_ComponentDispatch+0x16058a
00000000 00000000 00000000 00000000 00000000 QuickTimeMPEG4!EatMPEG4ComponentDispatch+0x6e
		

Credit

Discovered by Ryan Pentney and Richard Johnson of Cisco Talos