Storage or use of previously found sensitive information
MEDIUM | |||
Detection method | DAST API |
Description
An application stores or uses sensitive information in its operation.
During its operation, an application often handles sensitive information such as passwords, various tokens, encryption keys, etc. During the analysis of the application Mobix detects such information according to the search rules and additionally checks if the found sensitive information is stored unchanged or is used by the application in other functions or is “embedded“ in the source code of the application.
Recommendations
If you need to use sensitive information in the application, make sure that it is stored correctly and does not escape to public places, such as system logs (logcat) or application files on the SD-card.
If it is necessary to store such information, it is recommended to use encryption. To ensure privacy, Android is equipped with many cryptographic features and methods that allow Android applications to securely encrypt and decrypt (to ensure privacy), as well as perform message authentication (MAC) and digital signatures (to verify integrity).
In order to select an encryption method and key type suitable for the given conditions, you can use the following scheme:
Encryption/decryption using Android KeyStore
As an example, let's consider encryption/decryption using Android KeyStore. This mechanism allows you to generate and use keys generated in the Android hardware key store. This approach is the most secure in terms of key storage because the private key never appears in memory, which minimizes the risk of leakage orcompromise.
Creating new keys
Before you start the encryption process, you must set the alias that will be used to encrypt/decrypt the data. This can be any string. Alias is the entry name to refer to the generated key in the Android KeyStore.
First, you need to get an instance of Android KeyGenerator
final KeyGenerator keyGenerator = KeyGenerator
.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");
This example uses the AES algorithm and the keys will be stored in AndroidKeyStore.
Next you need to create a KeyGenParameterSpec, using KeyGenParameterSpec.Builder to pass to the initialization method KeyGenerators.
What is KeyGenParameterSpec?
KeyGenParameterSpec is some properties of the keys that will be generated. For example, you can specify the validity period of a key, its purpose, and various other parameters.
final KeyGenerator keyGenerator = KeyGenerator
.getInstance(KeyProperties.KEY_ALGORITHM_AES, ANDROID_KEY_STORE);
final KeyGenParameterSpec keyGenParameterSpec = new KeyGenParameterSpec.Builder(alias,
KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
.setBlockModes(KeyProperties.BLOCK_MODE_GCM)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
.build();
In the example above, the first argument is the alias, that will be used to refer to this key. Then the purpose of this key is specified - to encrypt and decrypt data. The setBlockModes specifies the mode for using this key. Since we use the "AES / GCM / NoPadding" conversion algorithm, it is necessary to specify BLOCK_MODE_GCM (ENCRYPTION_PADDING_NONE ).
Data encryption
The presets are now complete. The following example can be used to encrypt data:
final KeyGenerator keyGenerator = KeyGenerator
.getInstance(KeyProperties.KEY_ALGORITHM_AES, ANDROID_KEY_STORE);
final KeyGenParameterSpec keyGenParameterSpec = new KeyGenParameterSpec.Builder(alias,
KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
.setBlockModes(KeyProperties.BLOCK_MODE_GCM)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
.build();
First the keyGenerator is initialized using keyGenParameterSpec. After that - the SecretKey.
Now a secret key is available, you can use it to initialize the Cipher object, which is actually responsible for the encryption.
final KeyGenerator keyGenerator = KeyGenerator
.getInstance(KeyProperties.KEY_ALGORITHM_AES, ANDROID_KEY_STORE);
final KeyGenParameterSpec keyGenParameterSpec = new KeyGenParameterSpec.Builder(alias,
KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
.setBlockModes(KeyProperties.BLOCK_MODE_GCM)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
.build();
keyGenerator.init(keyGenParameterSpec);
final SecretKey secretKey = keyGenerator.generateKey();
final Cipher cipher = Cipher.getInstance(TRANSFORMATION);
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
iv = cipher.getIV();
encryption = cipher.doFinal(textToEncrypt.getBytes("UTF-8"));
Then a reference to the initialization vector (IV) is used. This vector is also required for decryption. Using doFinal (textToEncrypt) we finish the encryption operation. The doFinal method returns an array of bytes, which is the encrypted text.
Data decryption
Launching KeyStore
Before we can start decrypting data, we need a KeyStore instance.
keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
KeyStore is used to get a private key using the alias that was previously used to encrypt the data.
You need SecretKeyEntry from the key store to get the secretKey.
keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
final KeyStore.SecretKeyEntry secretKeyEntry = (KeyStore.SecretKeyEntry) keyStore
.getEntry(alias, null);
final SecretKey secretKey = secretKeyEntry.getSecretKey();
GCMParameterSpec with Cipher to initialize the decryption process (the encryptionIv parameter is the initialization vector that was used for encryption).
keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
final KeyStore.SecretKeyEntry secretKeyEntry = (KeyStore.SecretKeyEntry) keyStore
.getEntry(alias, null);
final SecretKey secretKey = secretKeyEntry.getSecretKey();
final Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
final GCMParameterSpec spec = new GCMParameterSpec(128, encryptionIv);
cipher.init(Cipher.DECRYPT_MODE, secretKey, spec);
And, as we did before, to get the decrypted data:
final byte[] decodedData = cipher.doFinal(encryptedData);
To get an unencrypted string representation:
final String unencryptedString = new String(decodedData, "UTF-8");
The complete source code of the example.
Links
3. https://developer.android.com/reference/javax/crypto/KeyGenerator.html
4. https://developer.android.com/reference/android/security/keystore/KeyGenParameterSpec.html
5. https://developer.android.com/reference/android/security/keystore/KeyGenParameterSpec.Builder.html
6.https://developer.android.com/reference/android/security/keystore/KeyProperties.html
7.https://developer.android.com/reference/javax/crypto/SecretKey.html
8.https://developer.android.com/reference/javax/crypto/Cipher.html
9.https://developer.android.com/reference/javax/crypto/spec/GCMParameterSpec.html