Friday, March 8, 2013

Security Testing iOS Apps Part 2

In part 1 of this series we focused on the basic skills required for iOS security testing. Now that you are an expert on all things iOS, it is time to set up the test environment. For this, some essential hard- and software is required.

1. Test device

For some apps (and if you have the full, compilable source code), it can be sufficient or even more reasonable to test on the iOS simulator only. However, there are situations where you want to run the app on the actual device, so you will most likely want to buy a test device. An iPad is obviously the better choice because it is not only cheaper, but can run iPhone apps as well.

If you are buying an iDevice for testing purposes, make sure to buy a device running an iOS version for which at least a tethered jailbreak is available. Just a few weeks ago, if you had bought a new iPad mini, you would have been stuck with a non-jailbreakable device, because a jailbreak for iOS 6 on A5 devices wasn't available yet. Apple also won't allow flashing an old iOS version, even if you still have the old firmware image lying around.

2. XCode and IOS API

Xcode is the toolset for building OS X and iOS applications. It has a nice IDE and integrates Apple's LLVM compiler. The iOS SDK allow you to compile applications for iDevices, as well as test them in the iPhone simulator. More information is available on the XCode website.

3. IDA Pro

I don't use many commercial tools for hacking (there's three paid tools I use in total) but there is simply no way around IDA Pro - it has been my trusted companion since version 4.3 or so. It is the most popular disassember and has great support for Objective-C binaries. AFAIK there is no alternative for disassembling iOS apps but if you know one, please let me know in the comments. Check out the Hex-Rays website for more information.

Black box or white box?

There are different test scenarios depending on what the client can and wants to provide you with.

In my opinion, pure blackbox testing of iOS apps usually does not make a lot of sense. Yes, you can look at the GUI and network traffic and interaction with the filesystem and iOS APIs, but it is so much more efficient to simply read the source code. Therefore we almost always try to go for a whitebox test / source code review.  If the source code cannot be obtained, it is standard procedure to disassemble the app, which is almost as good as having the code.

In the ideal case, you will always want the application's full source code including the XCode project files. This allows you to compile the app and debug it in the simulator, setting breakpoints etc. This is the easiest way to analyze the app's behavior and do a comprehensive security analysis.

Loading and debugging a project in XCode is pretty self-explaining - simply follow the XCode user guide.

However there are cases where only an IPA file or iTunes link is provided. This is the more difficult scenario, since you will not be able to use the simulator and you have to rely on reading the disassembly and observing the app's behavior on the device for your analysis.

Disassembling an iOS app

Analyzing an app obtained from the Appstore is not as straightforward as you would expect, because iPhone binaries are tied to a specific device using binary encryption - the binary can be decrypted only with the hardware key of the device for which the app was purchased. The decryption is done at run-time by the iPhone loader. Opening the encrypted binary in IDA Pro will give you only garbage.

Fortunately this is not a big issue if you have a jailbroken iDevice. All you need to do is dump the decrypted binary from memory using Stefan Esser's dumpdecrypted tool:

1. Jailbreak the device and install SSH if you haven't already

2. Download and compile dumpdecrypted. The IOS SDK is needed to compile it. Edit the makefile to point to the gcc in your SDK and run make, then copy the resulting dylib over to the device.

3. SSH into your device and search for the path to your app's main binary (somewhere in /var/mobile/Applications/). The run the binary with the DYLD_INSERT_LIBRARIES environment variable set to the dumpdecrypted library:

# DYLD_INSERT_LIBRARIES=dumpdecrypted.dylib /var/mobile/Applications/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/ mach-o decryption dumper

This will dump the decrypted binary into the file YOUR-APP.decrypted, which should load in IDA Pro just fine.

Reading Objective-C disassembly

Understanding Objective-C disassembly can be confusing at first. As you already know Objective-C uses message passing instead of normal function calls. The drawback of this is that you won't be able to generate useful call graphs, and it is more difficult to navigate through the binary.

To make things easier, make sure to use at least IDA Pro 6.2, which is able to parse Objective-C 2.0 metadata structures and generate a disassembly that is quite readable. A typical method call is realised via _obj_msgSend and looks like the following:

When calling _objc_msgSend, r0 points to the object name, r1 points to the method name, and the return value is stored in r0. The method call above translates too:

[[NSAutoreleasePool alloc] init]

As you can see, current versions of IDA can annotate everything reasonably well so we know what's going on. If you are planning on doing security analysis of iOS apps, you should definitely have a look at some iOS binaries in IDA to learn how to navigate through and understand Objective-C disassembly.

Here are some more pointers to interesting articles:

With the test setup finished, we will focus on the actual security analysis in the next episode.