- Speaker: Chris Varenhorst (Dropbox)
- Date: Thursday 30 January 2014
- Duration: 1h
- Location: MIT, Cambridge, MA
Slides are available here.
Backend APIs used by mobile apps
Almost every application uses an API to communicate with the backend.
APIs usually use HTTP or HTTPS not only because they offer standard ways to communicate and exchange data, but mainly because it is the easiest way to go through firewalls.
Common design problems
Certain APIs return content based on a URL only with no other protection, because this URL is never shown to the client. Access control restricts the private data returned to an authenticated user.
Naive APIs also do not apply abuse mitigation strategies that would prevent users to fetch huge amount of data.
Recent example: Snapchat API offered a way to look up contacts by returning a contact name based on his phone number. Someone abused this API and retrieved 4.7 millions phone numbers using brute force before publishing them on the web. There was no mitigation strategy preventing this behaviour.
Also, some APIs are too wide and generic. They send way too much information to the client application. The application does not show these data, but the data returned by the backend can be intercepted.
Reversing by observation
The easiest way to analyze a request1 is to set up a proxy on the phone that will listen to all the requests and responses exchanged between the phone and the world.
HTTPS is intended to prevent such ability. Certificate Authorities vouch for the application and it is not possible to listen to the data transferred. However, it is possible to install a fake Certificate Authority on the phone so that the client application now trusts the proxy. A caveat though: doing so seriously compromises the phone security.
It is impossible to install a Certificate Authority on Android and harder to make use of HTTPS than on iOS.
Make sure that phone and computer are on the same network so they see can each other. Once SSL has been set up on the proxy (Charles, in this case), it shows all the data sent to the phone via the network, requests and responses. Of course, it is then possible to replicate these requests from a computer to fetch the JSON content that can be returned by the server.
Google Maps returns blobs of data, which is much harder to interpret when doing reverse-engineering.
Reversing by decompiling
That only gives access to the requests but does not give clues on how transmitted data are actually used and/or decyphered.
It is then possible to inspect the client code. Usually, it is easier to log part of the code to understand what it does than to edit the code itself.
Example: instead of trying to decypher a complex private key sent from the backend, it is easier to wait for the application to decypher it for you and to log it somewhere.
This method is easier to do on Android because the code executed is bytecode, it is not low-level native code.
Genymotion is a much faster Android emulator than the official one provided from Google, but it requires some work to get the Google Play store working.
To process, the application first has to be copied from the device to the computer itself using adb. Then,
apktool decode my.apk sort of decompiles an application and produces a human readable code, between C and Assembly code syntax with registries.
A typical useful action is inserting some logging where the request is emitted and storing the log it inside a register newly created.
apktool build mypackage compiles the altered package and creates an APK that can be installed on the device using
adb push mynew.apk. apks have to be signed to run on an Android device, but creating a fake certificate is easy.
After recompiling, listening to the logged registry of the device is done using
adb -d logcat.
Designing APIs right/mitigation techniques
Limitating the maximum number of requests limits a user to abuse the API.
One can also delay feedback. For example, revoking the action made by a cheater a week after prevents them to understand what was wrong with their requests originally accepted by the server.
It is also possible to obfuscate the application code or the data transmitted using the API. It does not prevent abuse but makes reverse engineering much harder.
It is also possible to use certificate pining: the application only trusts one particular Certificate Authority, hardcoded in the client. The first method does not apply anymore, as a fake Certificate Authority will not be trusted anymore, but this filter can easily be removed using the second method.
All of these methods cannot prevent abuse but only slow down abusers, who cannot be slowed down forever. The best thing to do is to not rely on private APIs. Always develop public facing APIs to ensure that security will be taken care of at the API level itself.
Actually, sniffing paquets emitted on a wireless network is even easier, although this only works for HTTP requests. ↩