Talos Vulnerability Report

TALOS-2017-0262

Apple GarageBand Out of Bounds Write Code Execution Vulnerability

February 14, 2017
CVE Number

CVE-2017-2372

Summary

An exploitable out of bounds write vulnerability exists in the parsing of saved files in Apple’s GarageBand version 10.1.4. A specially crafted project file can cause an out of bounds write resulting in an exploitable condition. An attacker can deliver a project file via other means to trigger this vulnerability.

Tested Versions

Apple GarageBand 10.1.4

Product URLs

http://www.apple.com/mac/garageband/

CVSSv3 Score

8.8 – CVSS:3.0/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H

CWE

CWE-123: Write-what-where Condition

Details

Garageband is a music creation tool used to create new and original music easily from your computer. GarageBand comes installed for free with all new Mac purchases, meaning there is a large market of people who have this software installed on there computer. The file format used by GarageBand is a proprietary .band file. There exists a vulnerability in the parsing of this format. The format is broken into chunks each with a length field at the beginning of the chunk. This length is controllable by the user and no validation checks are done to ensure this length is in bounds thus leading to an exploitable condition.

The initial crash is shown below:

[rax: 0x00000001010f6f01] [rbx: 0x00007fff5fbfdb68] [rcx: 0x000000000000ffff]
[rdx: 0x0000000000000000] [rsi: 0x000000024ce301fe] [rdi: 0x00007fff5fbfdb68]
[rsp: 0x00007fff5fbee230] [rbp: 0x00007fff5fbee250] [ pc: 0x0000000100b4333d]
[ r8: 0x0000000000000002] [ r9: 0x0000000000000000] [r10: 0x000000018e041fa0]
[r11: 0x00007ffd12dbe040] [r12: 0x0000000000000003] [r13: 0x00007fff5fbfdb68]
[r14: 0x000000024e7ad9f8] [r15: 0x0000000100f4571a] [efl: 0x0000000000010202]

stop reason = EXC_BAD_ACCESS (code=1, address=0x24e7bd9f7)
GarageBand`___lldb_unnamed_symbol32314$$GarageBand + 125
GarageBand`___lldb_unnamed_symbol32314$$GarageBand:
->  0x100b4333d <+125>: mov    byte ptr [r14 + rcx], 0x0
    0x100b43342 <+130>: test   cl, 0x1
    0x100b43345 <+133>: je     0x100b4334d               ; <+141>
    0x100b43347 <+135>: inc    ecx

Shown above we can see a null byte being written out of bounds due to an invalid calculation of R14 and RCX. Looking through the current function we can see where these values come from. Starting with R14 it can be seen that this is a buffer on the heap. We run malloc history on it and the output is shown below:

ALLOC 0x25386f990-0x25386ffff [size=1648]: thread_7fff755a2000  openDocumentWithContentsOfURL:display:error:] | 0x10063c300 | -[NSDocumentController makeDocumentWithContentsOfURL:ofType:error:] | -[NSDocument initWithContentsOfURL:ofType:error:] | -[NSDocument _initWithContentsOfURL:ofType:error:] | 0x10057cfff | 0x10057cd55 | 0x1005b5cb1 | 0x100b5fc36 | 0x100b5c2c6 | 0x100b59528 | MAMem::Alloc(unsigned long) | malloc | malloc_zone_malloc

This is a buffer created for holding the data from our opened document. This means that RCX must be an index into this buffer. Looking where RCX comes from we are led a few lines above:

__text:0000000100B4331F                 lea     rsi, [rbp+var_12]  [0]
__text:0000000100B43323                 mov     rdi, rbx
__text:0000000100B43326                 call    qword ptr [rax+70h] ; 0x100af96d0   [1]
__text:0000000100B43329                 mov     rax, [rbx]we
__text:0000000100B4332C                 mov     rdi, rbx
__text:0000000100B4332F                 call    qword ptr [rax+90h]
__text:0000000100B43335                 movzx   ecx, word ptr [rbp+var_12]  [2]

At, [2], we can see var_12 being loaded into ECX only a few lines above our vulnerability. looking further we see this same variable, [0], passed in as the second argument to a dynamic function call. Tracing our input further, we follow it into the dynamic call below:

__text:0000000100AF96D0 read_bytes      proc near               ; DATA XREF: __const:00000001010F6FF0o
__text:0000000100AF96D0                 push    rbp
__text:0000000100AF96D1                 mov     rbp, rsp
...
__text:0000000100AF96DA                 mov     r14, rsi  [0]
...
__text:0000000100AF9732                 mov     word ptr [r14], 0
__text:0000000100AF9738                 mov     rdi, [rbx+10h]
__text:0000000100AF973C                 mov     rsi, [rbx+18h]
__text:0000000100AF9740                 mov     edx, 2
__text:0000000100AF9745                 mov     rcx, r14   [1]
__text:0000000100AF9748                 call    _CFDataGetBytes   [2]

As can be seen,[0], our buffer is moved into R14. It is then zeroed out, moved into the 4th argument, [1], for CFDataGetBytes,[2]. This function gets data from a buffer for a range, designated by RSI and EDX, and stores it into RCX. In this case the range it is extracting is 2 bytes. This extracted data is then used in our original calculation above to index into the original data buffer. The problem arises in the fact that the buffer that data being is extracted from, [2], is user controlled and no input validation is done on the bytes read in. This means that RCX is user controlled and can be any arbitrary 2 byte value. This leads to an exploitable null byte write anywhere.

Crash Information

Crashed thread log =
: Dispatch queue: com.apple.main-thread
0   com.apple.garageband10          0x000000010735d33d 0x10681a000 + 11809597
1   com.apple.garageband10          0x000000010735d24a 0x10681a000 + 11809354
2   com.apple.garageband10          0x0000000107373574 0x10681a000 + 11900276
3   com.apple.garageband10          0x00000001073762c6 0x10681a000 + 11911878
4   com.apple.garageband10          0x0000000107379c36 0x10681a000 + 11926582
5   com.apple.garageband10          0x0000000106dcfcb1 0x10681a000 + 5987505
6   com.apple.garageband10          0x0000000106d96d55 0x10681a000 + 5754197
7   com.apple.garageband10          0x0000000106d96fff 0x10681a000 + 5754879
8   com.apple.AppKit                0x00007fff8bf11b5a -[NSDocument _initWithContentsOfURL:ofType:error:] + 171
9   com.apple.AppKit                0x00007fff8bf11a46 -[NSDocument initWithContentsOfURL:ofType:error:] + 230
10  com.apple.AppKit                0x00007fff8bffd6c2 -[NSDocumentController makeDocumentWithContentsOfURL:ofType:error:] + 627
11  com.apple.garageband10          0x0000000106e56300 0x10681a000 + 6537984
12  com.apple.AppKit                0x00007fff8c23dedf -[NSDocumentController(NSDeprecated) openDocumentWithContentsOfURL:display:error:] + 798
13  com.apple.garageband10          0x0000000106dc2b5b 0x10681a000 + 5933915
...
36  libdyld.dylib                   0x00007fff82b345ad start + 1

log name is: ./crashlogs/5.crashlog.txt
---
exception=EXC_BAD_ACCESS:signal=11:is_exploitable=yes:instruction_disassembly=movb  $CONSTANT,(%r14,%rcx):instruction_address=0x000000010735d33d:access_type=write:access_address=0x0000000254b5d9f7:

Timeline

2016-12-15 - Vendor Disclosure
2017-02-14 - Public Release

Credit

Discovered by Tyler Bohan of Cisco Talos.