mardi 14 août 2012

Unlocking features on an iPhone application

Hi kids! Do you like dating?

Well I do, and last week I installed a new application on my iPhone 3g running iOS 4.2.1 (jailbroken).

That app (I will call it ZeApp) is a client - server app, based on a well known business model:
- users can create a profile
- they can publish advertisements (selling something, looking for something to buy, to rent, or someone to date...)
- they can view other users' profiles and ads
... for FREE

... BUT they need to pay to be able to communicate with eachother.

So there are some packages you can buy (classic, premium, 1 week, 1 year...) and depending on the package you bought, the features you can access change.

A lot of applications for selling things, auctioning, flat renting or selling, room sharing, couch surfing, dating and so on are based on this business model, and a lot of big companies make a lot of money with that.

Obviously, an application based on this business model will pay attention on the access control to the features, because if it can be circumvented, the company doesn't make money.

Surprisingly, it is not always the case...



Setting up the lab

For iOS application analysis, I use:
- a jailbroken device with ssh installed
- a wireless access point
- my laptop (ubuntu) with some tools (in this case a ssh client and burp suite)



Analyzing the app's environment

The first thing I do when I want to play with an app, is to inspect its environment: configuration files, databases, filesystem structure ...

Connect to the iDevice and look for the application directory:

jo@dp:~$ ssh root@192.168.55.11
root@192.168.55.11's password:


iPhone-de:~ root# find /var/mobile/Applications/ -name "*ZeApp*"

/var/mobile/Applications/1EF11D0A-69D4-4389-A13C-9FF73BC51FD1/Documents/ZeApp.sqlite
/var/mobile/Applications/1EF11D0A-69D4-4389-A13C-9FF73BC51FD1/Library/Preferences/com.ZeApp.iphone.plist
[...]

Then cd to the app's directory, which should be an ugly long hexa sequence.
At that time I usually look for plist files, which are configuration files. Once found, I use plutil to whether view the files or convert them to text for scp'ing them to my laptop.



iPhone-de:/var/mobile/Applications/1EF11D0A-69D4-4389-A13C-9FF73BC51FD1 root# ls
Documents/  Library/  ZeApp.app/  iTunesArtwork  iTunesMetadata.plist  tmp/
iPhone-de:/var/mobile/Applications/1EF11D0A-69D4-4389-A13C-9FF73BC51FD1 root# find . -name "*.plist"
./Documents/userdata.plist
./Library/Preferences/.GlobalPreferences.plist
./Library/Preferences/com.apple.PeoplePicker.plist
./Library/Preferences/com.ZeApp.iphone.plist
./ZeApp.app/Info.plist
[...]


One plist file is particularly interesting: com.ZeApp.iphone.plist, let's take a look!


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>APNSLastDeviceToken</key>
<string>(...)cb9f22e369c50940be4</string>
<key>AlreadyConnectedOnce</key>
<true/>
<key>AuthIsOn</key>
<true/>
<key>AuthenticationFirstLogin</key>
<date>2012-07-10T08:46:36.285761Z</date>
<key>AuthenticationLogin</key>
<string>myLogin</string>
<key>AuthenticationLoginCount</key>
<integer>1</integer>
<key>AuthenticationPassword</key>
<string>myPassword</string>
<key>AuthenticationRemember</key>
<true/>
[...]


My credentials are stored in cleartext in this plist file! First fail...

The are some other plist files that contain interesting data such as a list of action-permission pairs for client side access control. But unfortunately, those settings are overwritten everytime the app restarts.

OK, now that we know what settings are stored in plist files, let's see if there are some databases around...


iPhone-de:/var/mobile/Applications/1EF11D0A-69D4-4389-A13C-9FF73BC51FD1 root# find . -name "*.sqlite"
./Documents/ZeApp.sqlite

Let's copy it to the laptop and open it with sqlitebrowser...

jo@dp:~$ scp root@192.168.55.11:/var/mobile/Applications/1EF11D0A-69D4-4389-A13C-9FF73BC51FD1/Documents/ZeApp.sqlite ./myAnalysisDir

jo@dp:~$ sqlitebrowser myAnalysisDir/ZeApp.sqlite

In fact I'm not gonna show you the DB.
But I can tell you what's in it: it contains much more information than you can have by just using the app in a regular way (unless you subscribe). And no data in the database is encrypted...

But at this point nothing very surprising, using cryptography seems to be a mess for a lot of developers, so they often just don't.

Ok that's it for the application's environment. We located the configuration files, the databases, and we now know what data the application manipulates and stores, and where it gets it's settings from.

Now let's see how it communicates with the server.






Network traffic analysis


To analyse the network traffic you have several aproaches, and my favourite is the active one: you MITM so that you can both monitor and tamper with the transmitted data.

To do  that, I use ssh port forwarding to redirect the traffic to my laptop's port Burp is listening on. (thanks to @AndrivetSeb for the trick!)

Let's do it:

jo@dp:~$ burp &
jo@dp:~$ ssh root@192.168.55.11 -R 8080:localhost:8080
root@192.168.55.11's password:

Then you need to configure your phone to use a proxy on your wifi AP:
- go to Settings > Wifi > YourNetworkName > HTTP Proxy
- set your local proxy to the port you specified (so Server:127.0.0.1, Port: 8080)

And activate interception on burp. Done. You are in the middle.


When the app is launched, it sends my credentials to the server to log me in:



We can see here that the credentials are sent over HTTP in cleartext. Second fail....
The server's response sets a bunch of cookies and contains a session id which will be used to identify me in the following requests. If someone intercepts the request or the response, he can use my session and date the girls I'm supposed to date...

The next stages are funny:

The application asks the server for my account state.

The response contains the type of offer I subscribed, and the date my subscription expires, my account number, my email address, my login and my (obfuscated) password.

If I know the identifiers of premium subscriptions, I can trick the app so that it thinks I'm a premium member.
If someone intercepts this he has access to useful information such as my password length or my email address (which is a threat for my anonymity, and can be used for spam or phishing).




After that, the app asks the server for the acces control rules. The server returns a list of action-permission pairs. This list looks like this:

{"resultset":{"result":{"method":"rights","response":{"rights":{"id":{"LIST_EVENTS":{"type_pass":null},"MAIL_SEND":{"type_pass":["PASS_PREMIUM","PASS_PREMIUM"]}}}}}}}


This clearly means that the action "LIST_EVENTS" is available for all users, and the action "MAIL_SEND" requires a premium subscription.

And now you start to see what can be tried to trick the application: change the server response to allow any action to any subscription type!

To automate that, burp has a very useful feature. In the proxy tab, we can define find and replace rules.  We only need to replace ["PASS_PREMIUM","PASS_PREMIUM"] by 'null'.


And it worked! In the application, all the buttons are active now. I'm able to send a message to the girl of my dreams:



The server should deny the action, if it is designed correctly. But it is not!

I tried the other 'paid' features and it worked too. I fully unlocked the application and am able to enjoy all features for free.

It means that the server does not perform access control for the requests coming from the mobile application. The access control is only done by the mobile application according to the access control rules received from the server!

This is very bad. It is a very common mistake in web applications and webservices.

And thanks to that mistake, I no longer spend money to meet girls. However I still have to pay for drinks and dinner, but it's another problem...



How could it be better?


Obviously, the problem here is that the server trusts the mobile application too much. And the trick presented here is harmless, but I bet it is possible to attack the server by sending unexpected data (could lead to SQL injections for instance).

As recomanded by OWASP, the server shall never trust the client application. It should perform its own access control, and validate data received from the user. And the same stands for the client application regarding the server.


A few thoughts about this


I was very surprised of this weak access control mistake. The web version of the service performs the access control correctly on the server side. I expected the mobile application to use the same server side logic.

Another funny aspect of that app is that the executable code is obfuscated in a way that IDA hangs when I try to open it for further analysis. I don't really understand the point: why hardening the binary, when the application security is so weak? All config files are cleartext, the network data is cleartext, and the access control is  a big fail.

I certainly will analyse the obfuscation technique, and I may post about it later.


Finally, something bothers me. When you look at the method parameters for sending a mail, you can see that the destination is a user id. The user id is just a number. So we can imagine how easy it can be to spam all the users once a session (or credentials) is owned. This can be a quite interesting vector for spamming, phishing and social engineering.

1 commentaire: