|
C.J. MayInformation security professional and passionate programmer |
Mobile apps play an integral role in our use of technology. They handle all sorts of data from our lives, including our communications, finances, health, and entertainment. Mobile operating systems have done a great job of abstracting away the details of how mobile apps work from end users.
Because of the façade of polish that mobile apps have, we can forget that they, too, leak secrets. It’s not only possible – research has shown that mobile apps are among the worst offenders when it comes to leaking secrets. Cybernews did research in 2022 that found a staggering 56% of apps on the Google Play Store had hardcoded secrets that were able to be uncovered through automation. To learn more about their findings, you can check out GitGuardian’s webinar with one of the Cybernews researchers.
The reason for the high percentage of apps that leak secrets may be due to the conflicting guidance around mobile secret management. There are a lot of misinformed guides out there about the best way to handle mobile app secrets. The TL;DR is that you shouldn’t be putting secrets inside your mobile app. In this article, we will dig deeper into why that is and what to do instead. The end goal is to give you a good understanding of mobile app secrets and how to manage them properly so you can have confidence in the security of your application.
An important distinction we should make before talking about mobile app secret management is the difference between user secrets and developer secrets. This blog post will be focused more on developer secrets, because they are trickier. However, we should still talk about what user secrets are and how they should be handled so we understand the differences.
User secrets refer to the credentials and information belonging to each individual user. This includes data like passwords, PINs, authentication tokens, and other personal information. User secrets aren’t shipped with an application, they are configured after the app is installed and used. There are two main concerns when it comes to managing user secrets in mobile apps.
The first thing to be careful of is accidentally including valid test secrets in your app when it is built. If your testing methodology includes using real account credentials, you need to make sure that they don’t accidentally end up in your app when it is published.
The other best practice for managing user secrets is to use proper storage on the device. When storing sensitive user data, you should use encryption and secure storage APIs like Keychain on iOS or Keystore on Android.
In addition to accessing and manipulating user data, most apps use third-party services that support the basic functionality of the app. A developer secret might be an API key to a usage tracking service or a storage backend. Mobile apps need to access these services somehow, and the easiest way to do it is to hard-code the credentials into the SDK or requests. However, packaging secrets with your mobile app is an anti-pattern that should be avoided.
Earlier in this blog post, I alluded to the fact that there is a lot of misinformed guidance around mobile secret management. It’s not uncommon to see advice that claims injecting obfuscated or encrypted secrets at build time is enough to keep your app’s secrets safe. Let’s examine why that doesn’t work.
There are multiple approaches you can take to reverse-engineer a mobile app and recover information inside of it. The simplest method is to perform static analysis using a mobile security tool like MobSF. Below is an example of a MobSF scan report, which includes checks for clear-text secrets.
In this static scan, the API key was embedded in plain text inside the application’s source code. Sometimes obfuscation or encryption can defeat static analysis like this, but that doesn’t mean it’s enough to protect secrets. MobSF also has a dynamic analysis mode that lets you test a live application while recording information.
Eventually, a secret will need to be in memory or in a network request when it’s used. Using dynamic analysis sandboxes, you can even recover credentials that are encrypted at rest in the application’s source code.
The bottom line is that anything stored on the client side can be reverse engineered and discovered. You can make it more difficult to reverse-engineer or discover information inside of your app, but the only way to completely prevent a secret from being stolen from your app is to not include it in the app in the first place.
If you can’t keep any secrets in the app, what do you do? A mobile app isn’t the only technology that suffers from this dilemma. JavaScript-based websites are similarly challenged. In both scenarios, the solution has to do with where you execute the code: the client or the server.
Rather than trying in vain to securely store your secrets in the client app, you need to rewrite your code so that the secrets and integrations are on the server side. Instead of using client-side SDKs or making requests to the third-party service directly, you make the requests through a server you control. Ideally, this request to your backend is also user-authenticated so you can restrict requests to registered users and identify abuse.
If your app is using a third-party service or SDK that requires an API key, you need to try to move that logic to the backend which is under your control. If that’s impossible for some reason, then you need to take a good, long look at the benefits of that integration and weigh them against the potential risks of a malicious actor abusing that access.
If for some reason you are unable to avoid the secret touching your app, you should at least store the secret on the backend and send it to the app at runtime (and use certificate pinning). It’s not safe from dynamic analysis, but you can at least rotate the secret easily and often without having to republish your app.
Whatever you do, don’t ship secrets with your app.
At times, there are “secrets” that aren’t truly sensitive. A couple of examples might be a test credential that is only used for unit testing, or credentials to an empty database that is only used for local development on your workstation. In GitGuardian’s secret detection platform, you would typically “ignore” these types of secrets. The common theme here is that non-sensitive secrets are either ephemeral or using them has zero impact on your business.
Let’s look at a common mobile-specific example: Firebase API Keys. Firebase API keys aren’t like API keys that most other services use. They are just an identifier for your backend resources. The actual access and controls are restricted through Security Rules and App Check. So, it may be okay to include Firebase API Keys in your mobile app if you are configuring access control through the methods available to you. In general, though, it is on you to understand whether your secrets grant access to sensitive functions or data.
If you’re not sure whether something is a secret or not, you should ask yourself these kinds of questions:
Leaked secrets can have major implications, including sensitive data access, business logic manipulation, incurring costs on your dime, or even full system compromise. If a credential or API key has the power to do any of those things, keep it out of your mobile app’s code.
Handling mobile app secrets securely is not just a best practice; it's a necessity in today's digital landscape. In addition to following the advice above, you can implement GitGuardian’s secret detection platform into your software development pipeline to catch secrets at any stage of your app’s lifecycle. By incorporating these strategies and continuously improving your approach to security, you can significantly enhance the protection of your applications and the critical data they handle.
*** This is a Security Bloggers Network syndicated blog from GitGuardian Blog - Automated Secrets Detection authored by Guest Expert. Read the original post at: https://blog.gitguardian.com/how-to-handle-mobile-app-secrets/