iOS App Security and Analysis: Part 1/2

Learn how to do a basic analysis of iOS app security and maintain the security of your users’ data with code and network tools. By Derek Selander.

Leave a rating/review
Save for later
Share

iOS App Security and Analysis

You’ve worked hard on your app and it’s in the store. Maybe there are in-app purchases, or you’re storing user credentials, or you solved an NP-complete problem and want to be the only app in the store that can solve the 3SAT problem efficiently. But how secure are your app’s code and data?

In this two-part tutorial, you will be taking on the role of a penetration tester, evaluating your iOS app security to identify vulnerabilities. The goal of this tutorial’s unique teaching perspective is not to turn you into a hacker – it is rather to make you more security-conscious by showing common methods attackers use to circumvent your application’s logic and retrieve important user data.

The biggest point this tutorial will begin with, reiterate, and end with is that no application is truly secure. If someone is determined and smart enough, they will find vulnerabilities in your app. There is no guaranteed way to prevent attacks to your app’s logic. At least, short of not releasing the app at all! :]

However, there are best practices to hinder and frustrate attackers, pushing them to look elsewhere for more vulnerable, less informed prey!

You should be reasonably experienced using Terminal to follow along with this tutorial – you don’t need to be a master, but if you don’t understand a command or flag, you shouldn’t be afraid to man what you are doing. There won’t be too much code here, but you should have a good grasp of general Objective-C and Cocoa concepts.

Getting Started

Although attacks usually occur on jailbroken devices, you don’t need such a device for the purposes of this tutorial. Instead, you’ll use the good old Simulator. There are at least three big benefits of using the Simulator:

  • You don’t need to jailbreak your device to follow this tutorial.
  • You can learn and perform these attacks without learning how to do it on an actual device. That’s right, this tutorial will purposely omit some specific information you would use to attack a real app.
  • Doing these attacks on the Simulator is 100% legal.

You will be using the following tools in this tutorial:

  • The command line utility class-dump-z.
  • Charles, a web debugging proxy application. You can demo Charles for 30 days, though you can only run it for 30-minute periods during this time.

Attackers can have many different motivations for targeting your app. They could be doing it for fun, profit, curiosity or, as Alfred would say, “Some men just want to watch the world burn.” So as to give you a motivation to “creatively explore” an app, let me paint the following scenario for you:

Imagine that a fun new app has come out for the iPad called Meme Collector. The whole world loves it. However, you know from “friends” (aka Reddit) that this game makes you pay a considerable amount of money for in-app purchases.

free_memes_for_all

Your goal as an attacker is to find the logic that will let you have the app content (the memes) for free. There are a number of ways to do this and this tutorial will walk you through each one, as well potential ways to best defend against it.

As your first step to greater code warrior wisdom, download Meme Collector.

Note: Due to the complexity of this tutorial, certain shortcuts have been built into the project to make setup and analysis easier for you. For example, “purchasing” more app currency fakes a request to StoreKit, while in reality performing all the logic on the device.

Application Mapping

Your initial goal is to get a good bird’s eye view of the application. This includes what the application does from the user’s point of view, as well the basic structure that the app uses.

Fire up the Xcode project and run it on the 6.1 Simulator. Make sure you’re running your application in Release mode. To enable Release mode for a build, click on your scheme and select Edit Scheme.

sec-scheme1

Select the Run Meme Collector action in the left panel. Then in the Info tab, select Release under Build Configuration.

sec-scheme2

Build and run the app in the simulator. For the moment, try to refrain from looking at any of the source code. Imagine you are an attacker seeing this application for the first time. You only have access to the application, not its source files.

Meme Collector Start

This simple app allows you to purchase a meme while showing you an item count of your purchases, as well as how much currency you have remaining. Click on the items until you do not have enough currency to make another purchase. Now tap the Purchase Currency button to verify that you can purchase more in app currency.

All in all, it seems pretty basic. You can purchase memes and you have some currency that you can deplete, in which case you must purchase more. Again, your goal as an attacker is to get more memes without having to press the Purchase Currency button.

Now that you have a basic understanding of what the app does visually, it’s time to peak behind the curtains and see what information you can obtain about this app.

If you haven’t already, download the excellent little command line utility called class-dump-z that will display all the Objective-C declaration information found in the executable.

Unzip the downloaded bundle and in Terminal, navigate inside the unzipped directory to class-dump-z_0.2a/mac_x86. Here you’ll find a file called class-dump-z. Install this however you might like. I personally like to copy it to my /usr/bin directory:

> sudo cp class-dump-z /usr/bin/

Once you’ve installed class-dump-z, stay in the Terminal application… yes, that text thingie you love so much. Through Terminal, you are going to navigate to the app directory that is installed on the Simulator.

Important: You will be using Terminal a lot in this tutorial. In code blocks, the > character symbolizes the command prompt and represents the lines you’ll be typing.

Type the following line into Terminal:

> cd ~/Library/Application\ Support/iPhone\ Simulator/6.1/Applications

This is the directory that holds all the user-created applications inside the Simulator. This directory could potentially have a bunch of directory names that hold all the apps that you currently have on the Simulator. Having just run the Meme Collector app, the most recently modified directory is the one into which you want to cd. The following command will do just that:

> cd `ls -tr | tail -n 1`

What does this voodoo command do?

  • The ls command lists all contents and directories in the current directory.
  • The -tr flags list the output so that the most recently created directories are ordered last.
  • The pipe takes the output of all that info and sticks it into the tail command.
  • The tail command shows the last amount of data and you are explicitly telling it to show only one line. You then cd> into the last directory.

So in summary, you are listing all the directories, ordering them from first to last, taking the last directory and changing directories into that.

If (and only if) you are having trouble with this command, you can also use the following command to hunt down the correct directory:

> find . -name "Meme Collector"

This is the directory that was just created on the Simulator when you ran your app from Xcode. For the rest of this tutorial, I will refer to this directory as your app directory.

Now cd into the Meme Collector.app directory. The rest of this tutorial will refer to this directory as the main application bundle.

First things first, you should check out what Frameworks the bundle links to. This can give you good insight into any important delegate methods, classes or other areas of interest. From Terminal, type:

>otool -L Meme\ Collector

You’ll see the following output:

Meme Collector:
	/System/Library/Frameworks/SystemConfiguration.framework/SystemConfiguration (compatibility version 1.0.0, current version 499.5.0)
	/System/Library/Frameworks/MobileCoreServices.framework/MobileCoreServices (compatibility version 1.0.0, current version 40.0.0)
	/System/Library/Frameworks/Security.framework/Security (compatibility version 1.0.0, current version 1.0.0)
	/System/Library/Frameworks/StoreKit.framework/StoreKit (compatibility version 1.0.0, current version 1.0.0)
	/System/Library/Frameworks/QuartzCore.framework/QuartzCore (compatibility version 1.2.0, current version 1.8.0)
	/System/Library/Frameworks/UIKit.framework/UIKit (compatibility version 1.0.0, current version 2380.17.0)
	/System/Library/Frameworks/Foundation.framework/Foundation (compatibility version 300.0.0, current version 993.0.0)
	/System/Library/Frameworks/CoreGraphics.framework/CoreGraphics (compatibility version 64.0.0, current version 600.0.0)
	/usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 227.0.0)
	/usr/lib/libSystem.dylib (compatibility version 1.0.0, current version 125.0.0)

The otool -L command lists the shared libraries and frameworks used by the app. Most notably in this case, the app uses the StoreKit framework. You can assume that this application has in-app purchase logic somewhere inside it. (Remember, though: for this tutorial the project is faking the StoreKit request. Nudge nudge, wink wink.)

Now for some more detailed snooping, you will use the class-dump-z utility. Type the following into Terminal to create a class dump file called ClassDump.txt:

> class-dump-z Meme\ Collector > ClassDump.txt

Now you have your skeleton of the application. Open ClassDump.txt in TextEdit through Terminal with the following command:

> open ClassDump.txt

Here’s what you will see:

Class Dump Results

Look at all those methods! Along with public interface for the classes, the attacker can even view all your private methods, instance variables and protocols. Glancing over the output of a full-fledged project can be tedious, but can provide tremendous insight into how the app’s internals work and interact.

As a newfound application explorer, try and hunt down all the singletons in this application. Hint: singletons will likely have class declarations (instead of instance ones), with keywords like “manager”, “shared” or “store” in their method names. If you see an interesting singleton, be sure to check out all its methods.

[spoiler title=”Meme Collector’s Singletons”]

  • Various AFNetworking classes
  • MemeManager is interesting! It contains:
    + (id)sharedManager
    @property(retain, nonatomic) AFHTTPClient *client
    @property(readonly, nonatomic) NSMutableArray *memes 
    - (void)memePurchased:(int)arg1
    - (void)getMemeInformation // This is a private method BTW
  • MoneyManager is interesting! It contains:
    @property(readonly, nonatomic) NSNumber *money
    + (id)sharedManager
    - (BOOL)saveState // This is a private method BTW
    - (void)loadState // This is a private method BTW
    - (BOOL)purchaseCurrency
    - (BOOL)buyObject:(id)arg1
  • SVProgressHUD
+ (id)sharedManager
@property(retain, nonatomic) AFHTTPClient *client
@property(readonly, nonatomic) NSMutableArray *memes 
- (void)memePurchased:(int)arg1
- (void)getMemeInformation // This is a private method BTW
@property(readonly, nonatomic) NSNumber *money
+ (id)sharedManager
- (BOOL)saveState // This is a private method BTW
- (void)loadState // This is a private method BTW
- (BOOL)purchaseCurrency
- (BOOL)buyObject:(id)arg1

[/spoiler]

Attackers will often do what you’ve just done and look for certain keywords in the class dump. For example, if an attacker wanted to see if there is any logic for dealing with a jailbroken device, searching the application for keywords such as: (is)jailbroken, security, etc. can provide some quick feedback.

How can you stop attackers from doing this? Well, there is good news and bad news.

The good news is: Apple does it for you automatically. When you submit your app to the App Store, Apple encrypts your binary with FairPlay encryption – the same type of encryption used for some iTunes content. Running class-dump-z on an encrypted binary will result in complete gibberish.

The bad news: it’s a fairly trivial matter to circumvent this defense. The process can be completed manually in about 10 minutes time and there are even tools that exist to automate it. Long story short, you must plan and expect your application to be decrypted. You must plan that attackers will see your classes, methods, instance variables, protocols… everything.

Sad_see_all_the_things