Hardcoded Cryptographic Key

ID

csharp.hardcoded_cryptographic_key

Severity

critical

Resource

Predictability

Language

CSharp

Tags

CWE:321, NIST.SP.800-53, OWASP:2021:A2, PCI-DSS:3.6.3, crypto

Description

Cryptographic keys that are hardcoded into source code can be easily extracted and exploited by malicious actors. This practice compromises the security of the application, as these keys are not changeable without altering the source code.

Rationale

Hardcoding cryptographic keys in source code is a risky practice as it exposes sensitive information that should remain secret. The concern arises because hardcoded keys are not modifiable without a code change, making them an attractive target for attackers who can access the source code or binaries.

Consider the following C# example:

using System;
using System.Text;
using System.Security.Cryptography;

class Encryptor
{
    // Actual values are put here in my source
    private static readonly byte[] Key = {
        0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
        0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF
    };
    // IV should be random as well !
    private static readonly byte[] Iv = {
        0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
        0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10
    };

    public static String Encrypt(string source)
    {
        using Aes aes = Aes.Create();
        // HARDCODED KEY USED HERE
        var enc = aes.CreateEncryptor(Key, Iv);
        var toEncrypt = Encoding.ASCII.GetBytes(source);
        var encrypted = enc.TransformFinalBlock(toEncrypt, 0, toEncrypt.Length);
        return Convert.ToBase64String(encrypted);
    }
}

In this example, the cryptographic key is hardcoded directly into the class. If this code is compiled and distributed, anyone with access to the binary can retrieve and misuse the key, nullifying any intended cryptographic protection.

Remediation

To remediate this vulnerability, cryptographic keys should be managed securely, never hardcoding them in source code. Instead, use environmental variables, configuration files, or dedicated secrets management services that provide secure storage and retrieval of sensitive data.

An alternative is to perform cryptographic operations using an external, managed service. Known as Key Management Services (KMS), they provide different features including key generation and storage, key rotation and lifecycle management, encryption / decryption and other cryptographic operations like digital signatures, key wrapping, secure random number generation, etc.

For the previous hardcoded key, the fix gets the key material from environment variable. KMS or a secrets vault could be used alternatively.

using System;
using System.Text;
using System.Security.Cryptography;

class Encryptor
{
    public static byte[] encrypt(String data) throws Exception {
        // FIXED: retrieve key from secure location
        // and generate a random IV as well
        byte[] key = retrieveKeyFromSecureLocation();
        byte[] iv = RandomNumberGenerator.GetBytes(16);

        using Aes aes = Aes.Create();
        var enc = aes.CreateEncryptor(key, iv);
        byte[] toEncrypt = Encoding.ASCII.GetBytes(source);
        byte[] encrypted = enc.TransformFinalBlock(toEncrypt, 0, toEncrypt.Length);

        // base64-encode both IV and encrypted data; the iv is needed for decryption
        byte[] result = new byte[iv.Length + encrypted.Length];
        Buffer.BlockCopy(a, 0, result, 0, iv.Length); // 16 bytes
        Buffer.BlockCopy(b, 0, result, iv.Length, encrypted.Length);
        return Convert.ToBase64String(result);
    }

    private static byte[] retrieveKeyFromSecureLocation() throws Exception {
        // Example of reading the key from a secure environment,
        // e.g., an environment variable or secure storage
        string base64Key = Environment.GetEnvironmentVariable("ENCRYPTION_KEY");
        return Convert.FromBase64String(base64Key);
    }
}

In the improved example, the method retrieveKeyFromSecureLocation() retrieves the key from a specified, secure location, such as an environment variable or configuration file. This approach enhances security by keeping the cryptographic keys outside the source code, allowing them to be rotated and managed without altering the application code.

References