Best Practice For Storing and Protecting Private API Keys in Applications

Best practice for storing and protecting private API keys in applications

  1. As it is, your compiled application contains the key strings, but also the constant names APP_KEY and APP_SECRET. Extracting keys from such self-documenting code is trivial, for instance with the standard Android tool dx.

  2. You can apply ProGuard. It will leave the key strings untouched, but it will remove the constant names. It will also rename classes and methods with short, meaningless names, where ever possible. Extracting the keys then takes some more time, for figuring out which string serves which purpose.

    Note that setting up ProGuard shouldn't be as difficult as you fear. To begin with, you only need to enable ProGuard, as documented in project.properties. If there are any problems with third-party libraries, you may need to suppress some warnings and/or prevent them from being obfuscated, in proguard-project.txt. For instance:

    -dontwarn com.dropbox.**
    -keep class com.dropbox.** { *; }

    This is a brute-force approach; you can refine such configuration once the processed application works.

  3. You can obfuscate the strings manually in your code, for instance with a Base64 encoding or preferably with something more complicated; maybe even native code. A hacker will then have to statically reverse-engineer your encoding or dynamically intercept the decoding in the proper place.

  4. You can apply a commercial obfuscator, like ProGuard's specialized sibling DexGuard. It can additionally encrypt/obfuscate the strings and classes for you. Extracting the keys then takes even more time and expertise.

  5. You might be able to run parts of your application on your own server. If you can keep the keys there, they are safe.

In the end, it's an economic trade-off that you have to make: how important are the keys, how much time or software can you afford, how sophisticated are the hackers who are interested in the keys, how much time will they want to spend, how much worth is a delay before the keys are hacked, on what scale will any successful hackers distribute the keys, etc. Small pieces of information like keys are more difficult to protect than entire applications. Intrinsically, nothing on the client-side is unbreakable, but you can certainly raise the bar.

(I am the developer of ProGuard and DexGuard)

How do you secure project-wide API keys in a mobile app

TL/DR: You don't.

Long answer:

Any key that is distributed with the app can be read by the app for it to use it. The app therefore has what it needs to read the key, even if it is encrypted or obfuscated. An attacker can use the same technique that the app would use, to obtain the key.

Equally, fetching the key form an external source does not protect it. Again an attacker can use the same channel to obtain a copy of the key.

Besides attacking the channel by which the app obtains the key (from an encrypted store inside the package, or from an external source), an attacker can also obtain it from the app's memory or by intercepting network transmissions.

The only secure solution is to never have a copy of the key on the end user device.

The key should be kept on a well secured server which will act as a middle-man between the user's device and the end service. Any requests by the client device to the end service needs to be routed via this server.

The server, having the "global project keys", should make the requests to the end service on the behalf of the end user, and return the result (and never any keys) to the client. For the client to use this server, a per-user authenticated session must be used. The server must validate this session for every request prior to forwarding the request on to the end service.

Summary:

Use a secure server between the client and the end service to make requests on behalf of clients using the global key.

EDIT:
Side note: There is a distinction that needs to be made between per-user keys and keys that are project-wide. It is acceptable to keep keys that are specific to one individual person on that user's device.

How to securely store a hardcoded API key on Android?

YOUR CHALLENGE

The purpose of it is to be able to send that key everytime I call a webservice that I've made, so I'm sure (or almost sure) that the call comes from the original app that I'm making and that will be published on the Play Store, and not from elsewhere.

This is a very hard task to achieve, but not impossible one and here is where one needs to make a deep dive in mobile API security and understand the mechanics behind it.

It's fundamental to have a clear understand between the difference of who is in the API request versus what is making that API request, otherwise any security solution you may devise/use may not have the intended results.

The Difference Between WHO and WHAT is Accessing the API Server

I wrote a series of articles around API and Mobile security, and in the article Why Does Your Mobile App Need An Api Key? you can read in detail the difference between who and what is accessing your API server, but I will extract here the main takes from it:

The what is the thing making the request to the API server. Is it really a genuine instance of your mobile app, or is it a bot, an automated script or an attacker manually poking around your API server with a tool like Postman?

The who is the user of the mobile app that we can authenticate, authorize and identify in several ways, like using OpenID Connect or OAUTH2 flows.

So, you need to think about the who as the user your API server will be able to Authenticate and Authorize access to the data, and you need to think about the what as the software making that request in behalf of the user.

REVERSE ENGINEERING

I also don't want to store my key in my code, also because it could easily be retrieved via reverse engineering.

That's very true, it's more or less easily achieved depending on the method used to hide the API key, as per the ones you mention:

I've also checked the other methods explained here, but they look like the API key could quite easily be retrieved thanks to reverse engineering.

No matter how secure the API key has been stored, be it in the Android Keystore, encrypted, obfuscated, etc, at some point the API key will need to be in plain text to be sent on the API request header, and in this moment it will be vulnerable to be extracted via static reverse engineering, via a MitM attack or via an instrumentation framework

I have wrote the article How to Extract an API key from a Mobile App with Static Binary Analysis to illustrate how easy it can be done:

The range of open source tools available for reverse engineering is huge, and we really can't scratch the surface of this topic in this article, but instead we will focus in using the Mobile Security Framework(MobSF) to demonstrate how to reverse engineer the APK of our mobile app. MobSF is a collection of open source tools that present their results in an attractive dashboard, but the same tools used under the hood within MobSF and elsewhere can be used individually to achieve the same results.

During this article we will use the Android Hide Secrets research repository that is a dummy mobile app with API keys hidden using several different techniques.

I also wrote another article to achieve it during runtime, Steal that Api Key with a Man in the Middle Attack:

In order to help to demonstrate how to steal an API key, I have built and released in Github the Currency Converter Demo app for Android, which uses the same JNI/NDK technique we used in the earlier Android Hide Secrets app to hide the API key.

So, in this article you will learn how to setup and run a MitM attack to intercept https traffic in a mobile device under your control, so that you can steal the API key. Finally, you will see at a high level how MitM attacks can be mitigated.

An instrumentation framework can also be used during runtime to hook into the code that uses the API key in order to extract it. For example with the popular Frida framework:

Inject your own scripts into black box processes. Hook any function, spy on crypto APIs or trace private application code, no source code needed. Edit, hit save, and instantly see the results. All without compilation steps or program restarts.

So, no matter what it's done to secure the API key, once it's on the API request will be vulnerable to be extracted.

MOBILE API SECURITY

Anything that runs on the client side and needs some secret to access an API can be abused in different ways and you can learn more on this series of articles about Mobile API Security Techniques. This articles will teach you how API Keys, User Access Tokens, HMAC and TLS Pinning can be used to protect the API and how they can be bypassed.

POSSIBLE SOLUTIONS

I recommend you to read this answer I gave to the question How to secure an API REST for mobile app?, especially the sections Hardening and Shielding the Mobile App, Securing the API Server and A Possible Better Solution.

The possible best solution for your problem is known by Mobile App Attestation, that will let your backend know that what is making the request is indeed a genuine and untampered version of your mobile app, as you wish to achieve:

The purpose of it is to be able to send that key everytime I call a webservice that I've made, so I'm sure (or almost sure) that the call comes from the original app that I'm making and that will be published on the Play Store, and not from elsewhere.

Do You Want To Go The Extra Mile?

In any response to a security question I always like to reference the excellent work from the OWASP foundation.

For APIS

OWASP API Security Top 10

The OWASP API Security Project seeks to provide value to software developers and security assessors by underscoring the potential risks in insecure APIs, and illustrating how these risks may be mitigated. In order to facilitate this goal, the OWASP API Security Project will create and maintain a Top 10 API Security Risks document, as well as a documentation portal for best practices when creating or assessing APIs.

For Mobile Apps

OWASP Mobile Security Project - Top 10 risks

The OWASP Mobile Security Project is a centralized resource intended to give developers and security teams the resources they need to build and maintain secure mobile applications. Through the project, our goal is to classify mobile security risks and provide developmental controls to reduce their impact or likelihood of exploitation.

OWASP - Mobile Security Testing Guide:

The Mobile Security Testing Guide (MSTG) is a comprehensive manual for mobile app security development, testing and reverse engineering.

How protect an API key?

Generally Google stores keys into Android Manifest or string.xml (res files). Those two files can be decompiled like any other. I think KeyStore is generally good practice to store private keys, so please take a look at KeyStore class and how to use it.

Also you can find pretty good article on this subject on github

How to secure API keys in applications that will be distributed to clients

The answer depends on a few variables:

  1. Is your source included?
  2. Is it possible to use a server to call the API for you? If so, can you also apply restrictions to the call that the server makes?
  3. Is using compiled code for where you store the key an option? If so, is it possible to obfuscate it?

Here are my suggestions for different scenarios from experience:

The source is not included and using a server is an option, and restrictions can be applied, however using compiled code is not an argument

Then use a server to make requests. Let's say you need to make a call to example.com/api/v1, and you want to call a specific function with a specific set of arguments, then you can only allow requests to that specific API, with that specific set of arguments, and that specific function. This way, it means nothing to a potential attacker since it only calls to one function and nothing else.

The source is not included, using a server is not an option, and compiled code is not an option either

Well, there's not much you can do, obfuscation is your best shot. The best way to do something like this is to hide it deep within your code, and make it obscure, etc., etc., etc.,

The source is included, using a server is not an option, but you can use compiled code

Use really obfuscated assembly and don't share the source for that if you can. For instance, you can have red herring instructions, and just like before, you should hide it deep in your code.

The source is not included, using a server is not an option, but you can use compiled code

For this it's the same as above, since the source for the assembly wouldn't be included

If I didn't list your scenario here, then feel free to comment and I'll edit my answer

Protecting API Secret Keys in a Thick Client application

Probably not.

Look into cryptography and Windows' built-in information-hiding mechanisms (DPAPI and storing the keys in an ACL-restricted registry key, for example). That's as good as you're going to get for security you need to keep on the same system as your application.

If you are looking for a way to stop someone physically sitting at the machine from getting your information, forget it. If someone is determined, and has unrestricted access to a computer that is not under your control, there is no way to be 100% certain that the data is protected under all circumstances. Someone who is determined will get at it if they want to.



Related Topics



Leave a reply



Submit