lcimeni / youtube

0 stars 0 forks source link

NowSecure static analysis: API keys or tokens hardcoded in the application #100

Open lcimeni opened 3 years ago

lcimeni commented 3 years ago

Finding Description

Keys or tokens for APIs were discovered in the application package or bundle. An attacker can potentially use this information to gain access to the associated APIs which can expose sensitive data, enable unauthorized access, permit data to be modified, or other malicious activity.

Evaluation criteria

These API keys should be checked to ensure that they do not provide unwarranted or unintended access to APIs or data.

Steps to Reproduce

Inspect the app's source code for hardcoded API keys that are listed in the Findings Evidence table. Then, determine if the hardcoded API keys are truly necessary or if a more secure method of secret sharing should be implemented. The automated NowSecure test performs reverse engineering on the application bundle to search for the presence of keys or tokens commonly used to access API endpoints. The test then looks in the files contained within the application bundle to find the sensitive API keys or tokens. From there, the test determines if the keys or tokens can be found inside native or third party code.

Business Impact

The app is storing secrets that can potentially be used to access data in an insecure manner. Anyone who downloads the app will have access to them as well as whatever resources they provide access to.

Remediation Resources

Recommended Fix

Secrets should not be included in code or other static resources such as the binary package wherever possible. Secrets should be shared securely from the application's backend. The sensitivity of API keys that were uncovered during this test should be analyzed. API keys tied to critical or privileged assets should never be included in an app.

Code Samples

Good Code Example (.kotlin)

fun generateSecretKey(): SecretKey {
val keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, ""AndroidKeyStore"")
val spec = KeyGenParameterSpec
.Builder(secretKeyAlias, KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT)
.setBlockModes(KeyProperties.BLOCK_MODE_GCM)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
.build()

keyGenerator.init(spec)
return keyGenerator.generateKey()
}

fun encrypt(data: String): ByteArray? {
val cipher = Cipher.getInstance(""AES/GCM/NoPadding"")
cipher.init(Cipher.ENCRYPT_MODE, getSecretKey())
iv = cipher.iv
return cipher.doFinal(data.toByteArray())
}

Bad Code Example Using JNI (.cpp)

"// within native-lib.cpp file 
#include <jni.h>
#include <string>

extern ""C"" JNIEXPORT jstring JNICALL
Java_com_packagename_APIKeyLibrary_getAPIKey(JNIEnv* env, jobject /* this */) {
std::string api_key = ""SECRET_API_KEY"";
return env->NewStringUTF(api_key.c_str());
}

// within activity to use API keys in 
init {
System.loadLibrary(""native-lib"")
}

// declare java native function with same name as in the native code
public native String getAPIKey();

// retrieve the API key securely
APIKeyLibrary.getAPIKey();"

Additional Guidance

Risk and Regulatory Information

Severity: info

Application

See more detail in the NowSecure Report

lcimeni commented 3 years ago

Update: The risk severity (CVSS score) of this finding has been modified from 0 to 10 by Lorenz Cimeni.

Powered by NowSecure Platform