XMLWordPrintable

    • Icon: Sub-task Sub-task
    • Resolution: Unresolved
    • Icon: Major Major
    • None
    • None
    • None
    • False
    • None
    • False

      Keys used in the application must be secured, and access to them must be controlled and made available to the fewest possible users. These keys must also be stored separately from their key-encrypting key.

      The following locations are recommended for storing a key-encrypting key:

      1. On a removable drive
      2. On a different system, where access to the key is controlled using secured authentication, authorized mechanisms and transmitted securely (such as with TLS)

      All hardcoded passwords or secret keys can be retrieved from a client. Unless a secure key management system is used, a skilled attacker can bypass simple client-side techniques to obfuscate key/passwords. Avoid storing hardcoded secret keys or passwords on a client at all times.

      When you need to store an application secret:

      • Where possible, use alternative APIs that do not need that secret.
        - For instance, use the user's Facebook session.
        
      • When an alternative method is not available, store the secret on a server and proxy the requests through it.
        - The server needs to perform all the required validations, including the whitelisting of actions that are allowed, and validating that a registered user is logged into the app on the mobile device (validating the session).
        
      • Use a secure keystore / keychain with a master password that is derived from a salt and a password that is entered by the user or retrieved from a safe location as described in the How-to for this countermeasure.

      Note: The key-encrypting key must be at least as strong as the data-encrypting key that it secures.

      Imported from SD Elements: https://redhat.sdelements.com/bunits/psse-secure-development/group-2-extended-functionality-offerings/amq-clients/tasks/phase/specifications/141-T248/

      How Tos:

      Java or Android Keystore

      • Java provides a KeyStore class (in 'java.security' package) that could be used to store application secrets on the client.
      • This code sample demonstrates how a certificate and a private key can be retrieved from a keystore.

      ****
      String keyStoreName = "MyKeyStore.ks";
      String myKeystorePassword="TEST";
      char[] pw = myKeystorePassword.toCharArray();
      FileInputStream f = new FileInputStream(keyStoreName);
      // You can also use PKCS12 keystores which are compatible with platforms
      // other than Java (if that's a concern).
      KeyStore keystore = KeyStore.getInstance("JKS");
      keystore.load(f, pw);
      // Certificate
      Certificate cert = keystore.getCertificate("certificateAlias");
      // Private key
      KeyStore.ProtectionParameter protParam =
      new KeyStore.PasswordProtection(pw);
      KeyStore.PrivateKeyEntry pkE = (KeyStore.PrivateKeyEntry) keystore.getEntry("PKAlias", protParam);
      PrivateKey pk = pkE.getPrivateKey();
      ****

      • Since accessing the data stored in the keystore requires the use of a master-password, the application should store the master-password (of the local keystore) somewhere. This master-password should either be stored on the server (received only after proper authentication), or be derived from a user-provided password (e.g. using Password-Based Key Derivation Functions 2 (PBKDF2)).
      • In the case of PBKDF2, the result will be a key that could be used as the master-key of keystore and will depend on a user-provided password and a salt (random) value. You should store the salt on the private storage of the application (private data folders of the application) and recalculate the key when accessing the keystore using the password and the salt. The salt does not need any extra protection. Be aware that the keystore master-password in this case will be dependent on a user password, which should be considered when any password change is attempted. The following piece of code shows how inputPassword and salt could be turned into a SecretKey (sk) for keystore.

      ****
      char[] inputPassword=

      {...};
      byte[] salt={...}

      ;
      SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA512");
      int iterations=1000;int keyLen=256;
      KeySpec params = new PBEKeySpec(inputPassword, salt, iterations, keyLen);
      SecretKey sk = skf.generateSecret(params);
      ****

      • You can convert the SecretKey to String and use it as keystore password (Base64 in Android):

      ****
      String stringSecretKey = Base64.encodeToString(sk.getEncoded(), Base64.DEFAULT)

      Similarly, in Java:

      String stringSecretKey = Base64.getEncoder().encodeToString(sk.getEncoded());
      ****

      See this article for guidelines on various uses of the Android Keystore System.

      Storing cryptographic keys and data

      This is a technology-agnostic guideline for locally storing keys and other cryptographic data. Although it is discouraged to save sensitive data on client, in some cases, developers need to store keys, certificates and sensitive data on mobile or client devices (for example a mobile browser needs to store user passwords). In other cases the developers need to securely store such data on the server.

      In those cases, sensitive data should be encrypted.

      Password Zero Conundrum
      An immediate question is "Where should developers store the master-key that is used for encryption?" The same question is raised when the certificates, keys, or secrets are stored in a secure key storage. The key storage (keystore or keychain) needs a master password to allow access to its content. This is a common challenge and coined the "password zero" or "secure introduction" problem in the industry.

      Different solutions to the password zero problem are available, but a popular technique in cloud computing is that an identity is configured by a trusted system and included with the new service during deployment. Upon initialization of the new service, the identity is presented to the security system and an API token is received. The token is used by the new service to authenticate to other system components. Security tokens are often ephemeral making the window of opportunity narrow for attackers if the token is disclosed or exfiltrated. If the identify of the system is compromised then all tokens being issued are suspended until an investigation determines the leakage vector and its secured. HashiCorp offers a product called Vault that solves a lot of problems in this space, https://www.vaultproject.io/.

      In the open source GitHub CI/CD world, keystore passwords are maintained in Travis and known only to Administrators. Scripts that are run during deployment reference these passwords via shell variables that are assigned at runtime by Travis (the trusted system). The segregation provides script designers and developers access to the stored secrets, without necessarily providing direct access to the secrets. Secrets are leveraged as necessary during build and operational processes by CI environment variables. The specifics of the solution to the password zero problem depends on the design of the system and components that collaborate in the solution. It's a difficult problem to solve in a platform independent way and likely the reason it's not addressed directly by many platform designers. For instance, JKS and PKCS#12 keystores are strong, but a password is required to open them and care and handling of these passwords is often ignored by designers.

      Storing Salts
      Developers should store salts on the private storage of the application (private data folders of the application) and recalculate the key when accessing the keystore, using the password and the salt. Salts do not require additional protections. Note that the keystore master-password in this case will be dependent on user password and this should be considered when any password change is attempted.

      Training Modules

      Defending Web Applications
      Defending JSP
      Defending .NET 5
      Defending JavaScript
      Defending PHP
      OWASP Top 10 2021
      Opsec Fundamentals
      Defending .NET 6
      Defending TypeScript
      Defending Java

              rh-ee-ataylor Andy Taylor
              sdelements Jira-SD-Elements-Integration Bot
              Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

                Created:
                Updated: