AzoftCase StudiesSecurity Assessment of Mobile Payment Apps: iOS Penetration Testing

Security Assessment of Mobile Payment Apps: iOS Penetration Testing

By Victor Kotov on October 2, 2013

ios penetration testing Security Assessment of Mobile Payment Apps: iOS Penetration Testing Image by Ahitagni Mandal

Recently, when developing a mobile payment app for iOS, we had to meet high security requirements, established for apps that deal with confidential data (i.e. credit card info). The app we were working on was a mobile top-up service that allows users to make quick payments to their wireless carrier. For this project, in addition to following the usual practices of secure mobile development, we carried out security assessments of the app and its supporting architecture.

The performed testing has proven to be very effective and revealed a number of security weaknesses. So, we decided to write a series of in-depth tutorials and share our methodology for doing an app security audit. 

The audit covers four main issues: application traffic analysis, privacy, local data storing and penetration testing. Today we’ll start with the most interesting and challenging task — the penetration testing (a.k.a. pentesting). Sadly enough, NDA forbids me from sharing the original project test results, but I’ll illustrate the theory with code snippets and screenshots for a random app of the same category. Let it be the "Pay with a card" app.

Tools you’ll need

JailBreak tool

For device

  • Cydia enables users to install applications that are not available on AppStore, all the apps for security assessment will be installed through Cydia; the app itself is pre-installed in iOS on jailbroken devices.
  • OpenSSH — a utility for a remote access to iOS devices via SSH.
  • Adv-cmds runs ps, kill, finger and other useful commands.
  • Sqlite3 — a database client.
  • Veency — a VNC server for iOS devices.
  • Tcpdump intercepts Internet traffic.
  • Grep — a search utility.
  • GNU Debugger — a good debugging, analysis and reverse engineering tool.

For desktop

  • Burp Suite — an Internet traffic analysing tool; multiplatform.
  • Wireshark — one more good Internet traffic analysing tool.
  • iExplorer — a file manager.
  • Cyberduck — SFTP client (SSH access).
  • Screen Sharing — a system utility for connection to a VNC server; works together with the Veency app installed on a device but can use any other VNC client.
  • 0xED — a hex editor.

JailBreak

Our pentesting procedure uses special utilities the installation of which is impossible if a device hasn't been jailbroken. Read how to do it:

  • Activate the DFU mode, watch how to do it: 
  • Follow the redsn0w wizard.

If a device has been jailbroken successfully, Cydia should run smoothly. If you see “Unable to Load” (untrusted server certificate) error message, it means that Cydia configuration needs a little work:

Penetration testing

Disclaimer: The test results below are presented exclusively for the purpose to illustrate the pentesting methodology.

Note: Since the app doesn’t actually restrict access, the penetration test below is just an instructional example given to illustrate the pentesting technique rather than a real test.

Let’s get started.

Step 1. The first thing to do is to find a path for the application, for example with Cyberduck:

iPhone-Viktor-Kotov:~ root# ls -ld /var/mobile/Applications/*/UPS.app
drwxr-xr-x 4 mobile mobile 7310 Apr 19 10:13 /var/mobile/Applications/006C94AD-C409-44FD-8980-40D004E6188D/UPS.app

iPhone-Viktor-Kotov:~ root# cd /var/mobile/Applications/006C94AD-C409-44FD-8980-40D004E6188D
iPhone-Viktor-Kotov:/var/mobile/Applications/006C94AD-C409-44FD-8980-40D004E6188D root# cd UPS.app

Step 2. Find an executable file:

iPhone-Viktor-Kotov:/var/mobile/Applications/006C94AD-C409-44FD-8980-40D004E6188D/UPS.app root# plutil Info.plist | grep Executable
    CFBundleExecutable = UPS;

Step 3. Use Cyberduck to copy the executable file from the device or get the file from the iTunes folder on the desktop.

pentesting cyberduck Security Assessment of Mobile Payment Apps: iOS Penetration Testing

Step 4. On the desktop run terminal and read the file information:

Kotov-Mac-mini-3:PayWithCard qwerty$ file UPS
UPS: Mach-O universal binary with 2 architectures
UPS (for architecture armv6):Mach-O executable arm
UPS (for architecture armv7):Mach-O executable arm<

As we can see, the file contains two components for different architectures:

  • armv6, supporting iPhone 3G and earlier versions, iPod Touch 2nd gen and earlier versions; 
  • armv7, supporting the newer versions of iPhone, iPod Touch, and all iPad versions.

Step 5. Use otool to make a request:

Kotov-Mac-mini-3:PayWithCard qwerty$ otool -f UPS
Fat headers
fat_magic 0xcafebabe
nfat_arch 2
architecture 0
    cputype 12
    cpusubtype 6
    capabilities 0x0
    offset 4096
    size 241456
    align 2^12 (4096)
architecture 1
    cputype 12
    cpusubtype 9
    capabilities 0x0
    offset 245760
    size 244816
    align 2^12 (4096)

Note: Hereinafter in the request results the important information is marked bold.

With otool make a request for upload commands:

Kotov-Mac-mini-3:PayWithCard qwerty$ otool -arch armv6 -l UPS | grep crypt
    cryptoff  4096
    cryptsize 163840
    cryptid   1

Step 6. Connect to the device via SSH:

Kotov-Mac-mini-3:~ qwerty$ ssh -l root 192.168.0.109
root@192.168.0.109's password:

Step 7. Now we need to receive a copy of the unencrypted executable file on the device. To do this, we need to calculate the start and end addresses:

  • start: cryptoff + 0x1000; for our case: 4096 + 0x1000 = 0x2000
  • end: start + cryptsize; for our cease: 0x2000 + 163840 = 172032 or 0x2A000
iPhone-Viktor-Kotov:/var/mobile/Applications/006C94AD-C409-44FD-8980-40D004E6188D/UPS.app root# gdb -e ./UPS
GNU gdb 6.3.50.20050815-cvs (Fri May 20 08:08:42 UTC 2011)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "--host=arm-apple-darwin9 --target=".Reading symbols for shared libraries . done

(gdb) set sharedlibrary load-rules ".*" ".*" none
(gdb) set inferior-auto-start-dyld off
(gdb) set sharedlibrary preload-libraries off
(gdb) rb doModInitFunctions
Breakpoint 1 at 0x2fe0c1fa
 __dyld__ZN16ImageLoaderMachO18doModInitFunctionsERKN11ImageLoader11LinkContextE;
(gdb) r
Starting program: /private/var/mobile/Applications/006C94AD-C409-44FD-8980-40D004E6188D/UPS.app/UPS 

Breakpoint 1, 0x2fe0c1fa in __dyld__ZN16ImageLoaderMachO18doModInitFunctionsERKN11ImageLoader11LinkContextE ()
(gdb) dump memory upsarmv6.bin 0x2000 0x2A000
(gdb) kill
Kill the program being debugged? (y or n) y
(gdb) q
iPhone-Viktor-Kotov:/var/mobile/Applications/006C94AD-C409-44FD-8980-40D004E6188D/UPS.app root#

Step 8. Make sure that executable file is the right size:

iPhone-Viktor-Kotov:/var/mobile/Applications/006C94AD-C409-44FD-8980-40D004E6188D/UPS.app root# gdb -e ./UPS
GNU gdb 6.3.50.20050815-cvs (Fri May 20 08:08:42 UTC 2011)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "--host=arm-apple-darwin9 --target=".Reading symbols for shared libraries . done

(gdb) set sharedlibrary load-rules ".*" ".*" none
(gdb) set inferior-auto-start-dyld off
(gdb) set sharedlibrary preload-libraries off
(gdb) rb doModInitFunctions
Breakpoint 1 at 0x2fe0c1fa
 __dyld__ZN16ImageLoaderMachO18doModInitFunctionsERKN11ImageLoader11LinkContextE;
(gdb) r
Starting program: /private/var/mobile/Applications/006C94AD-C409-44FD-8980-40D004E6188D/UPS.app/UPS 

Breakpoint 1, 0x2fe0c1fa in __dyld__ZN16ImageLoaderMachO18doModInitFunctionsERKN11ImageLoader11LinkContextE ()
(gdb) dump memory upsarmv6.bin 0x2000 0x2A000
(gdb) kill
Kill the program being debugged? (y or n) y
(gdb) q
iPhone-Viktor-Kotov:/var/mobile/Applications/006C94AD-C409-44FD-8980-40D004E6188D/UPS.app root#

Step 9. Now we need to copy the decrypted version of the executed file to the original one. For this we need to calculate the address using formula:

Architecture offset* + Encryption offset (cryptoff)
*In our case architecture offset = 0, because our device is iPhone 3G.

So, we get: 

4096 + 4096 = 8192

Kotov-Mac-mini-3:PayWithCard qwerty$ dd seek=8192 bs=1 conv=notrunc if=./upsarmv6.bin of=./UPS
163840+0 records in
163840+0 records out
163840 bytes transferred in 0.434001 secs (377511 bytes/sec)

Step 10. Next, in 0xED hex editor we are setting the encrypted flag to 0: open the overwritten executable UPS file and, depending on architecture you need, find the first occurrence (at the beginning of the file) “/usr/lib/dyld”, or the second occurrence (approximately in the second half of the file).

pentesting 0xed hex editor Security Assessment of Mobile Payment Apps: iOS Penetration Testing

Alt: Pentesting: Use 0xED hex editor to set the encrypted flag to 0.

Search for the bytes with the 0x01 (01) value and set each found byte to 0x00 (00) one by one. After each change save the file and check in terminal if the flag has changed:

Kotov-Mac-mini-3:PayWithCard qwerty$ otool -arch armv6 -l UPS | grep crypt
    cryptoff  4096
    cryptsize 163840
    cryptid   0

If it hasn’t, undo the change and go to the next byte until you find and change the right one. Usually the byte we need stands between /usr/lib/dyld and /System/Library/Frameworks/Foundation.framework/Foundation lines.

Step 11. After you have found the byte, make the class-dump:

Kotov-Mac-mini-3:PayWithCard qwerty$ class-dump-z -u armv6 UPS

Step 12. Save the log data to UPSClassesDumpLog.txt and start the analysis.

So, the quick UPS analysis revealed that UPSAppDelegate has @property(retain, nonatomic) DataManager* dataManager;

the class has the following interface:

@interface DataManager : NSObject {
...
}

@property(assign) BOOL isRemember;
@property(assign) BOOL pinLocked;
@property(retain, nonatomic) NSString* cardInRegistration;
@property(retain, nonatomic) NSMutableArray* payments;
@property(retain, nonatomic) NSString* temppass;
@property(retain, nonatomic) Card* oldestCard;
@property(retain, nonatomic) Card* defaultCard;
@property(retain, nonatomic) NSMutableArray* aps;
@property(retain, nonatomic) NSMutableArray* whiteList;
@property(retain, nonatomic) NSMutableArray* cards;
@property(retain, nonatomic) NSString* password;
@property(retain, nonatomic) NSString* balance;
@property(retain, nonatomic) NSString* login;
@property(retain, nonatomic) MSISDN* userMSISDN;
-(BOOL)containInWhiteList:(id)whiteList;
-(BOOL)isBelongToUser:(id)user;
-(id)getCard:(long)card;
-(id)getWgiteListRec:(long)rec;
-(id)getAps:(long)aps;
-(id)getPayment:(long)payment;
-(id)getPayments:(id)payments;
-(id)getPayments;
-(id)getWhiteList;
-(BOOL)isWhiteListAddingAlowed;
-(id)getAPS;
-(id)getCards;
-(id)getOldestCard;
-(id)getDefaultCard;
-(id)getCardInRegistraiton;
-(id)getUsersToPayMsisdn;
-(id)getUserMSISDN;
-(void)saveAuthData;
-(void)cleanAuthdata;
-(BOOL)loadStoredAuthData;
-(BOOL)isAuthdataStored;
-(void)dealloc;
-(id)init;

Let’s try getting the list of bank cards that are being registered. To do this we need:

1. Find the process ID:

iPhone-Viktor-Kotov:/var/mobile/Applications/006C94AD-C409-44FD-8980-40D004E6188D/UPS.app root# ps aux | grep UPS
root      1590   0.0  0.3   273044    360 s000  R+    3:40PM   0:00.02 grep UPS
mobile    1579   0.0  8.3   320816   9880   ??  Ss    3:39PM   0:03.22 /var/mobile/Applications/006C94AD-C409-44FD-8980-40D004E6188D/UPS.app/UPS

2. With Cycript connect to the process:

iPhone-Viktor-Kotov:/var/mobile/Applications/006C94AD-C409-44FD-8980-40D004E6188D/UPS.app root# cycript -p 1579
cy# 

3. Receive the app’s instance:

cy# var app = [UIApplication sharedApplication]
@""

4. Get the AppDelegate address:

cy# app.delegate
@""

5. Assign an address to our variable:

cy# var delegate = new Instance(0x1652a0)
@""

6. Get a dataManager address:

cy# delegate.dataManager
@""

cy# var dataman = new Instance(0x16fbf0)
@""

cy# dataman.cardInRegistration
@"**** **** **** ****"
cy# dataman.cards
null
cy# dataman.balance
null
cy# dataman.password
@"243314"
cy# dataman.login
@"923*******"

It’s still unclear what temppass is used for. It’s probably a token:

cy# dataman.temppass
@"AAACOwAaAsrLlGli2mHqImF4l9BbUmWG"

Further analysis requires a bank card authentication. Then we could see the format of the stored card data, and check if it’s possible to make a payment for a random number. Keep in mind that this is done solely for the sake of technique demonstration. In practice, the app allows to perform such actions without hacking.

cy# datMan.cards
@[""]
cy# var card = new Instance(0x188da0)
@""
cy# card.name
@"4276 **** **** 2642"
cy# card.type
0
cy# card.expiry
@"2016-01-31 18:00:00 +0000"
cy# card.mounthLimit
3000
cy# card.weekLimit
2000
cy# card.dayLimit
1000
cy# card.transactionLimit
500
cy# card.objectId
396392549

cy# delegate.paymentsNavController
@""
cy# delegate.paymentsNavController.rootViewController
cy# var navContr = new Instance(0x157da0)
@""
cy# navContr.rootViewController
cy# navContr.viewControllers
@[""]
cy# navContr.viewControllers
@["",""]
cy# var payContr = new Instance(0x1a6d00)
@""
cy# payContr.moneyAmount
@">"
cy# var moneyA = new Instance(0x1ae8d0)
@">"
cy# moneyA.text = 10
-[NSCFNumber _isNaturallyRTL]: unrecognized selector sent to instance 0x1af800
cy# moneyA.text = @"10"
@"10"
cy# payContr.targetField
@">"
cy# var phoneNum = new Instance(0x1b0d20)
@">"
cy# phoneNum.text = @"923*******"
@"923*******"
cy# [payContr payPressed]

After contacting the server, the app informed us that the operation can’t be performed because the minimum payment is 100 rubles.

Other security assessment practices

Today I only covered one aspect of security assessment — the penetration testing. There are more things you can do to ensure maximum security of your app. Stay tuned for more tutorials in which I’ll cover application traffic analysis, privacy, and local data storing.

VN:F [1.9.22_1171]
Rating: 4.4/5 (7 votes cast)
VN:F [1.9.22_1171]
Rating: +6 (from 6 votes)
Security Assessment of Mobile Payment Apps: iOS Penetration Testing, 4.4 out of 5 based on 7 ratings

&nbsp;
eBook

Best Practices for Secure Mobile Development

In this eBook, you will find an overview of best practices for developing secure mobile applications. You will learn about crucial security issues one should consider before hiring a mobile development team. The information is provided by Azoft's leading iOS and Android developers, who have years of experience dealing with security issues for mobile projects. Besides covering the basics of secure development, this eBook focuses on the importance of secure authentication, as well as data transferring and data storage.

Download 0,5 Mb
Content created by Victor Kotov