Where to keep static information securely in Android app?

ぃ、小莉子 提交于 2021-02-11 12:24:27

问题


In my Andorid app, am using few keys and tokens for authentication and initialisations. I need to store these static keys somewhere in app securely. At the same time, I need to access it in code as well. I am aware of SharedPreference and Gradle variables, which right now I use. I have tried Cryptography as well, but then I will have to store the secretKey also for decryption.
So, am searching for any workaround or proper solution. Any help will be highly appreciated.


回答1:


YOUR PROBLEM

Where to keep static information securely in Android app?

No matter where and how you store them, because from the moment you release your mobile app, any secret on it belongs now to the public domain.

I have tried Cryptography as well, but then I will have to store the secretKey also for decryption.

You can make this hard to be reverse engineered by static analysis by hiding it in the C code, using the JNI/NDK interface in Android, like I do in this Currency Converter Demo repo, but then if the attacker is not able to reverse engineer it this way, he will do it during run-time with an instrumentation framework, and a popular one is 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.

Another alternative it's to try to compute the secret keys at runtime, but then once more Frida will hook on the function that does this and extract the secret from it's return value.

A basic code example of computing an HMAC during run-time can be found the the ShipFast Demo repo:

private fun calculateAPIRequestHMAC(url: URL, authHeaderValue: String): String {

        val secret = JniEnv().getHmacSecret()
        var keySpec: SecretKeySpec

        // Configure the request HMAC based on the demo stage
        when (currentDemoStage) {
            DemoStage.API_KEY_PROTECTION, DemoStage.APPROOV_APP_AUTH_PROTECTION -> {
                throw IllegalStateException("calculateAPIRequestHMAC() not used in this demo stage")
            }
            DemoStage.HMAC_STATIC_SECRET_PROTECTION -> {
                // Just use the static secret to initialise the key spec for this demo stage
                keySpec = SecretKeySpec(Base64.decode(secret, Base64.DEFAULT), "HmacSHA256")
                Log.i(TAG, "CALCULATE STATIC HMAC")
            }
            DemoStage.HMAC_DYNAMIC_SECRET_PROTECTION -> {
                Log.i(TAG, "CALCULATE DYNAMIC HMAC")
                // Obfuscate the static secret to produce a dynamic secret to initialise the key
                // spec for this demo stage
                val obfuscatedSecretData = Base64.decode(secret, Base64.DEFAULT)
                val shipFastAPIKeyData = loadShipFastAPIKey().toByteArray(Charsets.UTF_8)
                for (i in 0 until minOf(obfuscatedSecretData.size, shipFastAPIKeyData.size)) {
                    obfuscatedSecretData[i] = (obfuscatedSecretData[i].toInt() xor shipFastAPIKeyData[i].toInt()).toByte()
                }
                val obfuscatedSecret = Base64.encode(obfuscatedSecretData, Base64.DEFAULT)
                keySpec = SecretKeySpec(Base64.decode(obfuscatedSecret, Base64.DEFAULT), "HmacSHA256")
            }
        }

        Log.i(TAG, "protocol: ${url.protocol}")
        Log.i(TAG, "host: ${url.host}")
        Log.i(TAG, "path: ${url.path}")
        Log.i(TAG, "Authentication: $authHeaderValue")

        // Compute the request HMAC using the HMAC SHA-256 algorithm
        val hmac = Mac.getInstance("HmacSHA256")
        hmac.init(keySpec)
        hmac.update(url.protocol.toByteArray(Charsets.UTF_8))
        hmac.update(url.host.toByteArray(Charsets.UTF_8))
        hmac.update(url.path.toByteArray(Charsets.UTF_8))
        hmac.update(authHeaderValue.toByteArray(Charsets.UTF_8))
        return hmac.doFinal().toHex()
    }

Bear in mind this is a simple solution, but even a sophisticated one would be vulnerable to Frida scripts used by an attacker.

SECURITY IN DEPTH

So, am searching for any workaround or proper solution. Any help will be highly appreciated.

Security is all about adding as many layers as you can afford in order to make it time consuming for an attacker to overcome all of them, and to raise the bar for the skill set necessary by an attacker.

So using C code to hide secrets, like the decryption keys, store encrypted secrets on the Android keystore will throw away the scripts kids, but will leave you vulnerable to attackers that know how to use Frida scripts to hook into your code.

In my Andorid app, am using few keys and tokens for authentication and initialisations.

If your are trying to secure the keys to access your API then you can read my answer to this question to understand that implementing the Mobile App Attestation concept will allow you to not need to store secrets to access your API server. For initializations purposes I would recommend that you move this logic to the backend, because any in app decisions can be modified/bypassed with instrumentation Frameworks

Also consider using strong obfuscation techniques for all your code base, that will add another layer of difficulty in the attacker steps to reverse engineer 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.



来源:https://stackoverflow.com/questions/61724202/where-to-keep-static-information-securely-in-android-app

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!