Weak database encryption password

  MEDIUM  
Detection method   DAST         API  

Description

The password used to encrypt the database does not meet the criteria of length, simplicity or frequency of use. The main parameter for the security of data storage in an encrypted database on a device is the password that is used for encryption. If the chosen password is too simple or is present in the database of the most common passwords, there is a high probability of finding a password and compromising the information.

Recommendations

When using a password to encrypt the database, there exists the question of how to store it securely. Upon successful authentication in the application, there are several options for the server part to send a secret that forms the password used to open or encrypt the database.

Another option is to generate an encryption key ( that can be used as a database password) based on the user password. In this case, there is no need to store the encryption key, as it is generated "on the fly" based on the password entered by the user:

Rules:

1. Explicitly define the encryption mode and block augmentation.

2. Use crypto-resistant encryption technologies including algorithm, block encryption mode, and block augmentation mode.

3. Use "salt" when generating a password-based key.

4. Use a sufficient number of hashing iterations while generating the key based on the password.

5. Use a key with a length that ensures cryptographic strength of the encryption.

package com.appsec.android.cryptsymmetricpasswordbasedkey;
 
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.util.Arrays;
 
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
 
public final class AesCryptoPBEKey {
 
    // *** 1 *** Specify the encryption mode and padding explicitly.
    // *** 2 *** Use intractable cryptographic technologies that include an algorithm, a block cipher mode and a padding.

    // Parameters passed to getInstance method of Cipher class: an encryption algorithm, a block encryption mode, a padding
    // the following values for this example: encryption algorithm=AES, block cipher mode=CBC, padding=PKCS7Padding
    private static final String TRANSFORMATION = "AES/CBC/PKCS7Padding";
 
    // The string used to get the instance of the class that will generate the key
    private static final String KEY_GENERATOR_MODE = "PBEWITHSHA256AND128BITAES-CBC-BC";
 
    // *** 3 *** Use a salt when generating a password-based key
    // The length of the salt string in bytes
    public static final int SALT_LENGTH_BYTES = 20;
 
    // *** 4 *** Use an appropriate hash iteration count when generating keys from passwords.
    // It specifies the number of mix repetitions used for key generation with PBE
    private static final int KEY_GEN_ITERATION_COUNT = 1024;
 
    // *** 5 *** Use a key length that ensures cryptographic strength of encryption
    // The length of the key in bits
    private static final int KEY_LENGTH_BITS = 128;
 
    private byte[] mSalt = null;
 
    public byte[] getSalt() {
        return mSalt;
    }
 
    private void initSalt() {
        mSalt = new byte[SALT_LENGTH_BYTES];
        SecureRandom sr = new SecureRandom();
        sr.nextBytes(mSalt);
    }
 
    private static final SecretKey generateKey(final char[] password, final byte[] salt) {
        SecretKey secretKey = null;
        PBEKeySpec keySpec = null;
 
        try {
            // *** 2 *** Use intractable cryptographic technologies that include an algorithm, a block cipher mode and a padding.
            // Getting a class instance for key generation
            // This example for the KeyFactory class, which uses the SHA256 algorithm to generate an AES-CBC 128-bit key
            SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance(KEY_GENERATOR_MODE);
 
            // *** 3 *** Use a salt when generating a password-based key
            // *** 4 *** Use an appropriate hash iteration count when generating keys from passwords.
            // *** 5 *** Use a key length that ensures cryptographic strength of encryption
            keySpec = new PBEKeySpec(password, salt, KEY_GEN_ITERATION_COUNT, KEY_LENGTH_BITS);
            // Clear the password. It's required to complicate the debugging and not put the password in the memory dump
            Arrays.fill(password, '?');
            // Key generation
            secretKey = secretKeyFactory.generateSecret(keySpec);
        } catch (NoSuchAlgorithmException e) {
        } catch (InvalidKeySpecException e) {
        } finally {
            keySpec.clearPassword();
        }
 
        return secretKey;
    }
}

In the future, the resulting key value can be used as a password to encrypt the database and there is no need to store it.

Links

1https://github.com/sqlcipher/android-database-sqlcipher

2. https://github.com/OWASP/owasp-mstg/blob/master/Document/0x05d-Testing-Data-Storage.md#sqlite-databases-encrypted

3. https://cwe.mitre.org/data/definitions/521.html