Tag Archives: Mobile

#wedskaas: What every developer should know about app security, part 1: How to handle API keys

A few weeks ago at Xamarin Dev Days Graz I was asked a question I’ve been asked many times before: How do I obfuscate my mobile app’s code? My answer is always a counter-question: What are you trying to achieve by obfuscating your code? I’ve gotten different answers to this question and I want to dig into some answers I’ve received in the past in this blog post series.

A common answer is that there is some key or certificate that needs to be protected in the code.

I don’t believe code obfuscation is a good solution to this problem. I believe there typically isn’t anything that requires obfuscation inside an app’s code. Any attempts at hiding things inside an app’s code will only increase the effort it takes to get at that information but will not prevent it.

Some solutions I’ve heard for hiding a key inside the app code:

  • Encrypt the key (using which key?)
  • Assemble the key from strings in different portions of your source code
  • Hide the key in the last bytes of an embedded image
  • Use a code obfuscation tool
  • Don’t put it into the app’s code at all but load the key from a backend after the app has been installed

Let’s look at API keys

Let’s look at why these keys are there in the first place. In most cases, the key is used to authenticate the app towards a backend which is commonly referred to as an API key. For example, if you look at the Parse SDK Getting Started in the Xamarin Component Store, you’ll find this:

What the API expects here is a unique app ID and a key. The key gives you access to your data on the backend. The big problem here is that this one key is being used by all instances of the app.

A team at the University of Paderborn did an experiment to see if they could find that key inside app bundles in the Google Play store for apps that were using Parse. Using a simple static code analysis was enough for some apps but combining that with a dynamic (runtime) analysis was enough to retrieve the API key for all apps that were analyzed. Think about it: At some point, the app will have to call the method ParseClient.Initialize() with the plaintext key in memory.

The team then went on to analyze what they could access using those extracted API keys. The least information they could get for each app was a list of verified user email addresses. In many cases, they had complete read or even write access to all database tables for each app’s backend. The data found ranged from pictures, location information, contact information, and sales information to data gathered by trojans (yes, even the bad guys used Parse as a backend).

Parse is just an example here. You can find these API keys used in many backends and there is hardly an app out there that does not use any API keys. Anyone who extracts that API key can do whatever is allowed with that API key. This may or may not be a problem depending on what type of API key is at hand. It’s important to put yourself into the position of an attacker: What could someone who gets ahold of your API key do with that key?

In the case of Parse, it would have been possible to add user management and additionally authenticate users to access resources. That way, the API key itself would not have allowed access to all this data.

Authenticate the user, not the app

If you’re designing your own backend, you need to think about what type of data it is you are exchanging with your backend. Sometimes it may be OK to have your app access data from the backend without providing any credentials. This may be true for information you could also put on an unauthenticated website. But many times, you will be exchanging non-public information with your backend. In this case, it is always better to authenticate not the app but each user. The advantages are:

  • You can fully control what each user can see, even after your app has been distributed.
  • You can revoke access for individual users without breaking access for all other users.

If an API requires an API key, call it from your backend

If you do have to use a service that requires an API key, it is usually best to not make that call from within your app. A better approach is to make an authenticated user request the information from your own backend and then let your backend make the 3rd party API call on behalf of the user. The advantages here are:

  • It is not possible for an attacker to extract the API key and use your account to access the 3rd party API.
  • You can control how many calls are made with your API key.
  • You can cache results from the API and reduce the number of calls necessary.
  • You can block individual users from using the 3rd party API.

To hear more about this topic, you can watch my Xamarin Evolve talk on app security or stay tuned on this channel for more posts in this blog series.

Building secure apps: Need help from app store operators

Communicating securely between a mobile app and a the corresponding backend is not a trivial task. Sure, nowadays we can write https and almost be certain our app is actually having encrypted communication with the right backend. However, just recently, I decided to do a communications check of apps on my iPhone using Fiddler as a proxy and was surprised to find that I could do a man-in-the-middle attack for an app I use regularly without the app noticing this. Apparently, the developers had opted to disable certificate validation (perhaps so the app would work with a developer backend that doesn’t have a pricey SSL server certificate installed) and forgot to turn it on again before publishing the app to the store.

However, there is an even better way to solve that problem that doesn’t involve buying an SSL server certificate. It’s called certificate pinning. Instead of relying on the operating system to check the validity of the presented server certificate by looking at its list of root certification authorities (which may contain entries the user is not aware of, see Superfish) developers can instruct their https calls to only accept a specific server certificate or, better yet, only certificates issued by a specific certification authority. This is not only much safer, it also avoids the costs of buying SSL server certificates.

So there we are, we have a method to ensure our app is talking to the right backend. The trickier part, though, is ensuring that whoever is making the call to our backend is actually who we think they are (i.e., our own app).

A simple approach to this problem would be to include an SSL client certificate in all requests to the backend, using a certificate whose private key is included as part of the app bundle. The problem with this is that it’s just not possible to hide the certificate well enough in our bundle to make it impossible to extract that certificate and its private key through reverse engineering. And since all clients would be using the same certificate, having that certificate compromised means we cannot tell if it’s acutally our app that is calling the backend.

The solution to this problem is to issue individual SSL client certificates to each device that is accessing the backend.

The vendors of Mobile Device Managament (MDM) software have great solutions that do exactly that. The problem is that these solutions can only be applied to devices that are in full control of the MDM solution. That’s great for internal apps on company devices but doesn’t help at all for apps you’re distributing to others.

Here is my proposal: App store operators should include a method to create an unique SSL client certificate upon installation of the app that is signed either using a certificate (public and private key) the app creator uploads into the app store or a certificate created by the app store vendor. This would make it very easy to check on the server side if a request is coming from an app that was actually distributed through the app store (and paid for, in the case of non-free apps) by using the signing certificate’s public key.

Such a feature could also be included in cloud backends like Azure Mobile Services where one could limit requests only to genuine apps and provide the corresponding functionality the client libraries accessing the backend.

All in all, this approach would greatly increase app communication security without much effort for the app developer. Now, how to convince the app store operators?

ALM Days 2015: Mobile in the Enterprise

The ALM Days 2015 took place on March 11 and 12 in Düsseldorf. For the first time, a mobile track was conducted. My talk had the title Mobile in the Enterprise and covered the challenges you meet when developing apps for enterprise use. The video (in German) is on Channel 9 and the slides (also in German) are on Azure.

Dariusz collected the track videos in his blog (including one in English by Xamarin’s Mike James).

The final track event was a panel discussion on cross-platform development strategies with Dariusz, Jörg, Daniel, and myself.