简体   繁体   中英

Securely Saving API Keys In Android (flutter) Apps

I know that this question has been asked many times. I've read all of them. I've searched this in Google but I still have questions that I wasn't able to find answers for.

Currently I'm storing API Keys in my app. Which yes is a bad practice. Now to the best of my knowledge I can use ProGaurd or DexGaurd to obfuscate. I can also use Keystore to securely store my api keys. Now for this part here' my question: - Obfuscation changes the name of variables and classes. My API Key will still be in that app when someone decompiles the apk file. Sure it might take more time, but how much more is it? For example 20 minutes? I feel like the bottom line is that they can use this key if they put some time and effort. Am I getting this wrong?

Now the other answer that I've seen on different websites was that I can store my keys on a server and then communicate that through my app.

  • How is that even possible? A server is going to send the api key to the app. If the hacker finds this url they can just open it and get the key. If I use a key to access the URL then i'm entering a never ending loop of keys. How would I do this?

  • Someone said that I can encrypt my keys and then decrypt them in the app once it's received. But can't people decompile my decryption function and figure out my key?

I was also told that Firebase Remote Config is going to be a safe method for storing my keys. But then there's another problem

  • How much safer is this method?
  • If I'm using a google services json file to identify my project, can't just people get my keys from the remove config part? Because I can't see any settings for remove config on my console in order to say who can access this and who can't. How can I securely store my api keys on Firebase?

  • And can't hackers just decompile the apk and just change the code and extract data from my firebase account? Because the google services json is there. If they print the data extracted can they access everything?

So what exactly should I do to safely use api keys for my third party applications? And some of these api keys are very valuable and some of them just get information from other servers. I just want to know the safest method to store these keys.

HOW HARD CAN IT BE TO EXTRACT AN API KEY?

My API Key will still be in that app when someone decompiles the apk file. Sure it might take more time, but how much more is it? For example 20 minutes? I feel like the bottom line is that they can use this key if they put some time and effort. Am I getting this wrong?

You say For example 20 minutes? ... Well it depends if you already have the tools installed in your computer or not, but if you have at least Docker installed you can leverage some amazing open source tools that will make it trivial for you to extract the API Key in much less then 20 minutes, maybe around 5 minutes, just keep reading to see how you may do it.

Extract the API Key with Static Binary Analysis

You can follow my article about How to Extract an API Key from a Mobile App with Static Binary Analysis where you will learn how you may be able to do it under five minutes, and this without any prior hacking knowledge, from where I quote:

I will now show you a quick demo on how you can reverse engineer an APK with MobSF in order to extract the API Key. We will use the MobSF docker image, but you are free to install it in your computer if you wish, just follow their instructions to do it so.

To run the docker image just copy the docker command from the following gist:

 #:/bin/bash docker run -it --name mobsf -p 8000:8000 opensecurity/mobile-security-framework-mobsf

So after the docker container is up and running all you need to do is to visit http://localhost:8000 and upload your mobile app binary in the web interface, and wait until MobSF does all the heavy lifting for you.

Now if you have your API key hidden in native C/C++ code, then the above approach will not work, as I state in the same article:

By now the only API key we have not been able to find is the JNI_API_KEY from the C++ native code, and that is not so easy to do because the C++ code is compiled into a.so file that is in HEX format and doesn't contain any reference to the JNI_API_KEY, thus making it hard to link the strings with what they belong to.

But don't worry that you can just use a Man in the Middle(MitM) Attack or an Instrumentation framework to extract the API key.

Extract the API Key with a MitM Attack

Just follow my article Steal that API Key with a Man in the Middle Attack to extract it in a device you can control:

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.

Oh but you may say that you use certificate pinning, therefore the MitM Attack will not work, and if so I invite you to read my article about Byapssing Certificate Pinning :

In a previous article we saw how to protect the https communication channel between a mobile app and an API server with certificate pinning, and as promised at the end of that article we will now see how to bypass certificate pinning.

To demonstrate how to bypass certificate pinning we will use the same Currency Converter Demo mobile app that was used in the previous article.

In this article you will learn how to repackage a mobile app in order to make it trust custom ssl certificates. This will allow us to bypass certificate pinning.

Extract with Instrumentation Framework

So if none of the above approaches works for you, then you can resort to use an instrumentation framework, like the very widely used Frida :

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 you do in the end a secret in a mobile app can always be extracted, it just depends on the skill set of the attacker and the time and effort he is willing to put in.

STORING API KEYS ENCRYPTED IN THE MOBILE APP?

Someone said that I can encrypt my keys and then decrypt them in the app once it's received.

So you can go with the Android Hardware-backed Keystore :

The availability of a trusted execution environment in a system on a chip (SoC) offers an opportunity for Android devices to provide hardware-backed, strong security services to the Android OS, to platform services, and even to third-party apps.

At some point the secret retrieved from this keystore will need to be used to make the http request, and at this point all an attacker needs to do is to hook an instrumentation framework on the call to the function that returns the API key decrypted to extract it when is returned.

And to find the decrypt function all an attacker needs to do is to decompile your APK and find it as you already though off:

But can't people decompile my decryption function and figure out my key?

FIREBASE AND SAFETYNET FOR THE RESCUE?

I was also told that Firebase Remote Config is going to be a safe method for storing my keys.

Once more all the attacker needs to do is to use an instrumentation framework to extract all it needs from any function he identifies as using the Firebase config.

Oh but you may tell that Firebase and/or your mobile is protected with SafetyNET, then I need to alert you for the fact that SafetyNet checks the integrity of the device the mobile app is running on, not the integrity of the mobile app itself, as per Google own statement :

The goal of this API is to provide you with confidence about the integrity of a device running your app. You can then obtain additional signals using the standard Android APIs. You should use the SafetyNet Attestation API as an additional in-depth defense signal as part of an anti-abuse system, not as the sole anti-abuse signal for your app.

Also I recommend you to read this answer I gave to the question Android equivalent of ios devicecheck? in order to understand what a developer needs to be aware when implementing Safety Net in their mobile app.

So despite SafetyNet being a very good improvement for the Android security ecosystem it was not designed to be used as a stand-alone defence, neither to guarantee that a mobile app is not being tampered with, for that you want to use the Mobile App Attestation concept.

PROXY OR BACKEND SERVER

Now the other answer that I've seen on different websites was that I can store my keys on a server and then communicate that through my app.

How is that even possible? A server is going to send the api key to the app. If the hacker finds this url they can just open it and get the key. If I use a key to access the URL then i'm entering a never ending loop of keys. How would I do this?

While you may say this only shifts the problem from the mobile app to the proxy or backend server I have to say that at least the proxy or backend server is a thing under your control, while the mobile app isn't. Anyone who downlaods it can do whatever wants with it, and you can't have a direct control of, you can only add as many barriers you can afford into the APK to make it hard.

I recommend you to read my answer to the question How to restrict usage of an API key with Hash comparison? to better understand why you shouldn't try to secure your API keys in your mobile app, and instead move them to your backend or a proxy server.

POSSIBLE BETTER SOLUTION

So what exactly should I do to safely use api keys for my third party applications? And some of these api keys are very valuable and some of them just get information from other servers. I just want to know the safest method to store these keys.

The best advice I can give you here is to read my answer to the question How to secure an API REST for mobile app? to understand how you can indeed get ride of API keys in the mobile app and allow for your backend to have a high degree of confidence that the request is originated indeed from a genuine instance of your mobile app.

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 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.

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.

If you think API Key should not be compromised then you should not put it inside the app. You can use the following possible solutions

  1. You can keep your keys on a server and route all requests needing that key through your server. So as long as your server is secure then so is your key. Of course, there is a performance cost with this solution. You can use SSL pinning to authenticate the response. Check this
  2. You can get the signature key of your app programmatically and send is to sever in every API call to verify the request. But a hacker can somehow find out the strategy.
  3. Google does not recommend storing API keys in remote config but you can keep one token there and use it to verify the request and send the API key. Check this
  4. In the case of the Android app, you can use SafetyNet API by Google to verify the authenticity of the app and the server can generate a token for the user after verification of the SafetyNet response. The token can be further used to verify the request. There is one plugin available for Flutter for SafetyNet API.

You can use a combination of the above approaches to ensure the security of the API key. To answer your questions, Firebase remote config uses SSL connection to transfer the data, it's very much secure but you should not rely on it completely for your data security. You also can't share API keys using the APIs which are publicly accessible. Moreover, storing both the encrypted key and the data inside the app won't make it secure.

You can use freeRASP for Android, iOS, and Flutter to mitigate the risk of Reverse Engineering.

The premium plans offer more protection such as App Integrity Cryptogram to protect APIs from app impersonation and Secure Storage SDK to protect assets at rest.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM