Skip to main content
iOS Application Security Review Methodology

iOS Application Security Review Methodology

Claudio Contin
IOS Mobile App Review

The following post aims to provide a high level overview of an iOS application security review methodology and an introduction of some tools publicly available to perform the analysis.

iOS Sandbox
#

Every application on an iOS device runs in a sandbox environment. This means that an app, if compromised, won’t be able to access another application data, unless iOS vulnerabilities themselves are exploited. The separation is maintained by the operating system and is based on four different key components:

  • Entitlements
  • Containers
  • Powerbox
  • XPC Services

Entitlements
#

In order to enable additional features such as iCloud, push notifications, or Apple Pay, an application needs to specify a list of entitlements. In other words, the fact that more features are enabled extends the application’s sandbox. An entitlement is a list of configurations included in the application’s signature.

Containers
#

In iOS, an application runs in its own container. When the application is launched, two environment variable are set for the application’s process: HOME and CFFIXED_USER_HOME. In this way, the operating system lets the application pretend that its own home directory is the one controlled by iOS. If access from the application is attempted to the real system user home directory, the sandbox denies it.

Powerbox
#

If an application tries to access files outside its own sandbox, the system denies access. iOS supplies a trusted mediator process, called Powerbox, that an app can call in order to explicitly require the user to have access to a file outside the app sandbox. If an application requires this kind of access, the user is prompted with a popup in order to select which file the app will be allowed access. Once the item is selected by the user, the file is provided directly to the application.

XPC Services
#

In order to allow the developers to perform privilege separation of the same application components, iOS implements an interprocess communication technology (IPC) called XPC. A single XPC service runs within its own sandbox, meaning that different XPC services might have a different set of entitlements. The XPC services of an application are accessible only by the application itself and the lifetime of is maintained completely by the operation system.

Need for Jailbreak
#

In order to perform a thorough review of an iOS application, a jailbroken device is advisable. There are a series of tests that can be performed on a non jailbroken device, but the review in this case would be limited. In this post, checks that can be performed on a non jailbroken device will be marked with (Jailbreak Unnecessary), whereas when jailbreak is necessary, the following tag will be specified. (Jailbreak Required). A good resource of tools to install on a jailbroken device in order to perform an application review, is available at: http://resources.infosecinstitute.com/ios-application-security-part-1-setting-up-a-mobile-pentesting-platform/

Remote API
#

Most of the mobile applications rely on an external Web API in order to perform user authentication, syncronisation or backup of local application data, etc. In order to perform a testing of the API, there is the need to proxy the mobile application requests through a controlled machine with a proxy running on it (Burp for instance). To setup the device to proxy requests to another host, please refer to the the official proxy guide. For Burp example, please see: https://support.portswigger.net/customer/portal/articles/1841108-configuring-an-ios-device-to-work-with-burp. This post won’t be focusing on potential remote API issues. A list of checks to perform on the local mobile applications for network communication are:

  • Plain Text Communication with Remote API
  • Lack of SSL Certificate Pinning
  • SSL Misconfiguration

Plain Text Communication with Remote API
#

Jailbreak Unnecessary

The first thing to check is that the application uses SSL/TLS for network communication. If clear text HTTP protocol is used, for instance, the application is vulnerable to Man in The Middle attacks and a potential attacker would be able to intercept and modify network data from and to the app and the API.

Lack of SSL Certificate Pinning
#

Pinning is the process of associating a host with their expected SSL certificate or public key.

Jailbreak Unnecessary

After the iOS device is setup to properly proxy the networking traffic through a controlled proxy, start the application and try to generate network traffic, by logging in for instance. If the application will refuse the connection, Certificate Pinning is properly implemented by the app. Otherwise, it is possible to perform Man in The Middle attacks on the mobile application traffic.

Jailbreak Required

If Certificate Pinning is implemented, try to use SSL Kill Switch in order to have a better understanding of the API endpoints and parameters the application calls.

SSL Misconfiguration
#

Jailbreak Unnecessary

During the development of mobile applications, developers might want to accept any self-signed SSL certificates in order to facilitate the development process. This check might be forgotten when the application is deployed in the Apple Store. One thing to check when reviewing an application is making sure that it does accept any kind of self-signed certificates.

Static Analysis
#

This post will use Yelp as an example. No vulnerabilities were found and no exploits will be performed on it. It was purely chosen in order to describe a methodology to review an iOS application. A static analysis of an application involves reviewing and reversing of the application binary. Below there is a list of tools and checks that can be performed.

Needle
#

Jailbreak Required

Needle is a tool released in August 2016 by MWR Infosecurity that aims to facilitate the review of iOS applications by relying on a series of tools installed on the device and the machine used to conduct the analysis. The current features available, as at October 2016, allow to conduct application binary, storage, dynamic and static (if source code access is available) analysis. It also allows hooking with Cycript and Frida. Needle is written in Python and can be easily launched from a shell with the following:

python needle.py

Needle takes a number of options in order to connect to the iOS device (which requires OpenSSH server running on it). In the following example, the iOS device IP is 192.168.2.3 and we want to connect to the default SSH port 22, and use the metadata module in order to extract some basic information

set IP 192.168.2.3
set PORT 22
use metadata
run

The result, which has been partially truncated, shows the path of the app on the device filesystem, which cpu architectures are supported, minimum iOS version, etc.

/private/var/mobile/Containers/Bundle/Application/2E2A51E9-B964-41B6-B360-34AD21CE2BE3/Yelp.app/Yelp
Architectures       : armv7, arm64
Platform Version    : 9.3
SDK Version         : iphoneos9.3
Minimum OS          : 8.0

A good module to have an overview of the application compilation flags is binary/compilation_checks. Things to check in this case are missing binary protections such as stack canaries, PIE, and Automatic Reference Counting ( ARC) .

Application Encryption
#

Jailbreak Required

All app on apple store are protected by Apple’s binary encryption scheme.

Needle allows to decrypt and pull locally the decrypted IPA. This post won’t purely focus on the use of Needle.

Dumpdecrypted is a good tool to decrypt iOS application binaries. It can be used in the following way:

DYLD_INSERT_LIBRARIES=/usr/lib/dumpdecrypted.dylib /private/var/mobile/Containers/Bundle/Application/2E2A51E9-B964-41B6-B360-34AD21CE2BE3/Yelp.app/Yelp

Yelp.decrypted will be created. In order to check the architectures supported by the binary, lipo can be utilised:

lipo -info Yelp.decrypted

The result of the previous command is:

Architectures in the fat file: /private/var/mobile/Containers/Bundle/Application/2E2A51E9-B964-41B6-B360-34AD21CE2BE3/Yelp.app/Yelp are: armv7 arm64

The same can be achived with Apple otool:

otool -vh Yelp.decrypted

Previous command result:

Mach header
      magic cputype cpusubtype  caps    filetype ncmds sizeofcmds      flags
   MH_MAGIC     ARM         V7  0x00     EXECUTE   116       9800   NOUNDEFS DYLDLINK TWOLEVEL WEAK_DEFINES BINDS_TO_WEAK PIE
/private/var/mobile/Containers/Bundle/Application/2E2A51E9-B964-41B6-B360-34AD21CE2BE3/Yelp.app/Yelp (architecture arm64):
Mach header
      magic cputype cpusubtype  caps    filetype ncmds sizeofcmds      flags
MH_MAGIC_64   ARM64        ALL  0x00     EXECUTE   116      10584   NOUNDEFS DYLDLINK TWOLEVEL WEAK_DEFINES BINDS_TO_WEAK PIE

Lipo can also be used to extract the executable for a specific architecture. In this example, armv7 will be used:

lipo -thin armv7 -output Yelpv7 Yelp.decrypted

Let’s now confirm only 1 architecture is supported in the new executable:

otool -vh Yelpv7
Yelpv7:
Mach header
      magic cputype cpusubtype  caps    filetype ncmds sizeofcmds      flags
   MH_MAGIC     ARM         V7  0x00     EXECUTE   116       9800   NOUNDEFS DYLDLINK TWOLEVEL WEAK_DEFINES BINDS_TO_WEAK PIE

Grab the executable to local machine:

scp root@192.168.2.3:/private/var/root/Yelpv7 .

The decryption process can be achieved manually by loading the application, attaching gdb to the process and dumping the memory location of unencrypted program to file. It is an option to consider in case available tools fail to do so. This process won’t be covered in this post.

By now having access to the unencrypted executable, it is not possible to inspect it with Hopper, IDA, or any other reverse engineering tools.

Below, a few screenshot of Hopper ran against the binary previously unencrypted:

Hopper Strings

Hopper View Controllers

Hopper Pseudo Code

Check for Plist Files
#

Jailbreak Unnecessary

An application may use plist files in order to store configuration information. Plist are a property list XML structured text files. When assessing an iOS application, one of the things to check is hardcoded credentials stored in plist files. A jailbroken device is not needed to access such files. i-funbox is a tool that can be used on any iOS devices to explore data in the application sandbox, including plist files.

Check for Keychain Data and SQLite DBs
#

Jailbreak Required

Keychain is a service provided by iOS in order to allow applications to store sensitive data, such as credentials or API access tokens. The keychain encrypts the data before storing it on the file system. Jailbreaking a device allows complete access to the data stored in the keychain. Keychain-Dumper is the current de-facto tool to dump all keychain data on a jailbroken device. When assessing an application, try to review what information the app stores in the keychain. It is recommendable that data stored in the keychain is encrypted with an extra encryption at the top of the keychain provided by the operating system. Even if the encryption key could be extracted by reversing the application binary, this would put off unexperienced attackers.

Jailbreak Unnecessary

In iOS, it is possible to store data in SQLite databases. The sqlite files are accessible in the application sandbox data directory. By default, SQLite databases are not encrypted. SQLcipher is a good alternative in order to encrypt them. When reviewing an application, make sure to check if it saves any data and what kind of data in SQLite databases, and see if encryption is performed.

Check for HTTP Caching Responses
#

Jailbreak Unnecessary

If the application makes use of the built-in NSURLRequest to perform HTTP requests, the responses might be cached on disk in the Cache.db SQLite file relative to the application. It the remote API/Web Server does not return Cache-Control header in the responses, sensitive information might end up being stored on the device. Note that the cache data stored in this file is not encrypted in any way.

MobFS
#

Jailbreak Required

MobFS is an open source tool to perform static and dynamic analysis of iOS and Android applications. In this post this tool won’t be covered, but it is worth check it out when performing a review. Note that jailbreak is only needed if the IPA is not provided and needs to be extracted from the device.

Dynamic Analysis
#

Dynamic Analysis consists in runtime manipulation of the application process in order to try to achieve the following:

  • bypass jailbreak detection
  • steal encryption keys or sensitive data
  • load ViewControllers to bypass certain controls
  • attack local authentication (if present)
  • pivot into internal networks when accessing corporate apps
  • check custom encryption

Instrumentation
#

Jailbreak Required

A number of tools exist to perform what is called instrumentation, which is the process of exploring and modifying applications at runtime. The more commonly known are:

  • Cycript
  • Frida
  • Cydia substrate
  • GDB
  • dynamic linker to override functions (LD_PRELOAD)

Cycript
#

Jailbreak Required

Cycript is an awesome tool to explore and modify running applications on iOS. It uses a hybrid syntax of Objective-C and JavaScript syntax. It can be started by passing the process name or PID of the application:

cycript -p Yelp

Once attached to the process, it is possible to explore the application components:

cy# UIApp
#"<UIApplication: 0x1667a760>"
cy# [UIApplication sharedApplication]
#"<UIApplication: 0x1667a760>"
cy# UIApp.keyWindow
#"<UIWindow: 0x17bdfd70; frame = (0 0; 768 1024); gestureRecognizers = <NSArray: 0x17f14270>; layer = <UIWindowLayer: 0x17d23150>>"
cy# UIApp.keyWindow.rootViewController
#"<YPUITabBarViewController_iPad: 0x17c30b90>"
cy# UIApp.delegate
#"<YPUIApplicationDelegate_iPad: 0x1667fd30>"

It is possible to invoke methods manually, change the current ViewController, etc.

In the following example we pretend that the YPUIApplicationDelegate_iPad class implements a method called correctCredentials that verifies user entered credentials, and returns true if the credentials are correct. Cycript allows to redefine methods at runtime. In this case, we want to always return true when this method is called:

cy# YPUIApplicationDelegate_iPad.prototype['correctCredentials'] = function(){return true;}
function () {return!0;}

The same could be achieved of the application has any kind of jailbroken protection.

When reviewing an application, check what kind of bypasses can be achieved by manipulating the process at runtime. If bypass of certain functionality can be easily achieved, this could indicate a design issue of the application itself.

Snoop-it
#

Jailbreak Required

Snoop-it is another great tool to perform dynamic analysis of iOS application. I personally found it a bit unstable, and often the process of the application crashed while running attached to Snoop-it. But otherwise, it provides a user friendly web interface and great functionality, which is described below.

Snoop-it Filesystem Module
#

This module monitors filesystem access of the application:

Snoop-it Filesystem

Snoop-it Crypto Module
#

This module tracks common crypto API calls:

Snoop-it Common Crypto

Snoop-it Fake Location Module
#

This module allows to provide a fake location when the application requests the current GPS coordinates of the device:

Snoop-it Fake Location

Snoop-it Hardware Spoof Module
#

This module permits to override the UDID and the Mac-Address of the device:

Snoop-it Hardware Spoof

Snoop-it Keychain Module
#

This module tracks what data is accessed or stored in the Keychain:

Snoop-it Keychain

Snoop-it Method Invoke Module
#

This module allows to invoke methods at runtime, in a similar way as previously described using Cycript:

Snoop-it Method Invoke

Snoop-it Method Tracing Module
#

This module allows to trace which methods are invoked during the execution of the application:

Snoop-it Method Tracing

Snoop-it Network Module
#

This module traces HTTP and HTTPS calls made from the application:

Snoop-it Network

Snoop-it Sensitive API Module
#

This module traces sensitive API calls, such as current device location, Mac Address of the wifi network interface, etc.:

Snoop-it Sensitive API

Snoop-it URL Schemas Module
#

URL schemes is a way to allow intercommunication between other applications. This module shows which URL schemas are implemented in the application:

Snoop-it URL Schemas

IDB
#

Jailbreak Required

IDB is another open source tool written in Ruby language that works in a similar way as Snoop-it. It does not allow to invoke methods dynamically like Snoop-it does, but it has a couple of more functionalities, such as checking system log and pasteboard, and fuzzing URL schemes.

IDB App Info
#

IDB App Info

IDB Keychain
#

IDB Keychain

IDB Log
#

IDB Log

IDB Pasteboard
#

IDB Pasteboard

IDB Shared Libraries
#

IDB Shared Libraries

IDB Storage
#

IDB Storage

IDB URL Handlers
#

IDB URL Handlers

introspy-ios / introspy-analyzer
#

Jailbreak Required

Introspy-iOS helps to automate the runtime analysis of the application and potentially identify security issues. Introspy-iOS (tracer) hooks and inspect sensitive API called by the application. It stores the results in a local SQLite database on the device. Introspy-Analyzer is a tool that helps with formatting the tracer data and generate a HTML report. Below an example of result of the tools hooked into Yelp application.

Introspy Potential Findings

Introspy Trace

Snapshot
#

Jailbreak Unnecessary

When an application is put in background, by pressing the device home button, iOS takes a screenshot of the current application screen. The screenshots are stored until the next device reboot. When reviewing an application, check if displays any sensitive information; if yes, try to put the application in background when the information is visible on the screen and inspect the screenshot taken by iOS. If the device is jailbroken, Needle, a tool previously described in this post, provides an easy way to perform this test and automatically downloads the screenshot for you. Otherwise, locate the file manually in the application sandbox directory using i-funbox.

Jailbreak Detection
#

Jailbreak Required

As a security in-depth measure, applications might decide to perform jailbreaking detection of the device and refuse to run otherwise. If sensitive data is stored on the device, the application might erase this data once the jailbreak is detected. When reviewing an application, check if jailbreak detection is performed and how effective the implementation is.

Anti-Debugging Protection
#

Jailbreak Required

As another security in-depth measure, an application might detect that it is running in debug mode with a debugger attached, such as GDB, and gracefully stop running. Even though experienced people would be able to bypass such protection, less experienced ones might get pulled off and started looking at another target.

Keyboard Cache
#

Jailbreak Required

When text is typed in input fields inside iOS applications, the data is cached for autocorrection, with the exclusion of password type fileds and other specific strings. When reviewing an application, check what data is being stored inside this cache.

Buffer Overflow / Format Strings / Memory Corruption
#

Jailbreak Unnecessary

iOS applications can be vulnerable to memory corruption vulnerabilities, such as buffer overflows and format strings. When doing a review, it is worth to try fuzzing user input and check for application crashes, that might indicate the application is vulnerable. If the testing device is jailbroken, a further crash analysis with a debugger can be performed.

References
#

Disclaimer
#

The information in this article is provided for research and educational purposes only. Aura Information Security does not accept any liability in any form for any direct or indirect damages resulting from the use of or reliance on the information contained in this article.