Skip to main content

Hard-Coded Secrets

Fixing hard-coded secrets

About Hard-Coded Secrets

What are Hard-coded Secrets?

Hard-coded secrets refer to the practice of embedding sensitive information, such as passwords, encryption keys, or API keys, directly in the source code of an application.

This practice can make it easy for attackers to identify and exploit these secrets, leading to security vulnerabilities and other types of security threats.

Hard-coded secrets are a security risk because they are often stored in plain text, making it easy for attackers to extract them from the source code. They can also be inadvertently disclosed or exposed through other security vulnerabilities, such as code injection or data leaks.

Hard-coded secrets can affect various types of applications, such as web applications, mobile applications, and desktop applications. They can also be found in infrastructure components, such as scripts, configuration files, and server software.

At GuardRails, we differentiate between different kinds of secrets and cover the below CWEs.

What is the impact of Hard-Coded Secrets?

Hard-coded secrets can lead to various security threats and risks, such as:

  • Information disclosure: Hard-coded secrets can expose sensitive information, such as passwords, keys, or other types of confidential information, to unauthorized parties.
  • Unauthorized access: Hard-coded secrets can allow attackers to gain unauthorized access to applications, systems, or networks, perform unauthorized actions, or modify data.
  • Data modification: Hard-coded secrets can allow attackers to modify data or system configurations, leading to data loss or corruption, or other types of system instability.

This has led to many high-profile breaches.

How to prevent Hard-Coded Secrets?

To prevent hard-coded secrets, implement appropriate security measures, such as:

  • Use environment variables: Use environment variables or configuration files to store sensitive information, such as passwords or keys, instead of hard-coding them in the source code.
  • Use secure storage: Store sensitive information in secure storage, such as a secure key vault, that provides additional security features, such as access controls and encryption.
  • Use encryption: Use encryption to protect sensitive information in transit and at rest, such as using TLS for network traffic and encrypting storage media.
  • Apply access controls: Apply access controls to limit the privileges and actions that users or applications can perform on sensitive information, such as using role-based access controls or fine-grained access controls.
  • Use secure coding practices: Follow secure coding practices, such as code reviews, vulnerability scanning and testing, and threat modeling, to ensure that the source code is free of vulnerabilities and that sensitive information is properly protected.

A list of popular secure key vault software can be found below:

  1. HashiCorp Vault
  2. AWS Secrets Manager
  3. GCP Cloud KMS
  4. Microsoft Azure Key Vault
  5. Confidant
  6. Keywhiz
  7. Knox

References

Taxonomies

Explanation & Prevention

Training

Directory Service Microsoft AD Password Set to Plaintext or Default Ref

The AWS::DirectoryService::MicrosoftAD resource has a property Password which must not contain a plain text value or a Ref to a parameter with a default value.

Both of the following solutions use AWS SecretsManager.

Rule-specific References:

Option A: Store the Password in SecretsManager and rotate it using a Lambda function

Courtesy of AWS.

The CloudFormation template for this option is available here.

Follow the instructions below:

  1. During the initial set-up (which can be performed either manually or through a CloudFormation template), the password of the admin user is stored as a secret in Secrets Manager. The secret is in the JSON format and contains three fields: Directory ID, UserName, and Password. The secret is encrypted using KMS Key to provide an added layer of security
  2. This secret is attached to a Lambda function that controls rotation
  3. This rotation Lambda function generates a new password, updates Active Directory, and then updates the secret. The function can be invoked on an as-needed basis or at the desired interval. The CloudFormation template provided above schedules the rotation at a 30-day interval
  4. Applications can securely fetch the new secret value from Secrets Manager
  5. Implement these steps
  6. Test it
  7. Ship it 🚢 and relax 🌴

Further details on this CloudFormation Issue.

DocDB Cluster Master Password In Plaintext

DocDB DB Cluster (AWS::DocDB::DBCluster) master user password (MasterUserPassword) must not be in a plain text string or a Ref to a parameter with a default value.

Specific References:

Option A: Use a Dynamic Reference to an AWS Systems Manager Secure String within Stack Template

Replace the plaintext password (MasterUserPassword) in the DocDB DB Cluster (AWS::DocDB::DBCluster) with a Dynamic Reference ('{{resolve:ssm-secure:MasterPassword:10}}') to an AWS Systems Manager SecureString parameter.

Follow the instructions below:

  1. Create a Systems Manager SecureString

  2. Reference the SecureString with a dynamic reference

    MyDBInstance:
    Type: AWS::RDS::DBCluster
    Properties:
    # ...
    MasterUsername: admin
    MasterUserPassword: '{{resolve:ssm-secure:MasterPassword:10}}'
    # ...
  3. Test it

  4. Ship it 🚢 and relax 🌴

ECS Task Definition Container With Plaintext Password

It's not recommended to use plaintext environment variables for sensitive information, such as credential data.

Specific References:

Option A: Make sure to not include passwords or other secret values in environment variables

Replace any plaintext passwords or other sensitive environment variables in task definitions by creating AWS Secrets Manager secrets or AWS Systems Manager Parameter Store parameters and then reference them in your container definitions.

For example, if you decided to use AWS Systems Manager Parameter Store:

  1. Create a parameter in AWS Systems Manager Parameter Store as type SecureString, for example, let's call it MY_PASSWORD and assign the value ("y0uC4ntT0uchMe") to it.

  2. Reference that parameter in your task definition in the secrets list instead of in the clear as an environment variable like the following:

    Move the following environment variable:

    {
    "family": "",
    "containerDefinitions": [
    {
    "name": "",
    "image": "",
    ...
    "environment": [
    {
    name = "password",
    value = "y0uC4ntT0uchMe"
    }
    ],
    ...
    }
    ],
    ...
    }

    To a proper secret that will be injected as an environment variable into your container:

    {
    "family": "",
    "containerDefinitions": [
    {
    "name": "",
    "image": "",
    ...
    "environment": [],
    "secrets": [
    {
    "valueFrom": "MY_PASSWORD",
    "name": "password"
    }
    ]
    ...
    }
    ],
    ...
    }
  3. Test it

  4. Ship it 🚢 and relax 🌴

User Data Contains Encoded Private Key

AWS ECS Launch Configuration User Data should not contain an encoded RSA Private Key. Encoding secrets does not protect them at all, it simply obscures them. Do not rely on obscurity as a technique to provide security.

Rule-specific references:

Option A: Make sure EC2 Launch Configuration User Data does not contain encoded RSA Private Key

If a launch configuration has base64 encoded UserData containing a private key, move it to a location with the purpose to store secret values in AWS such as the following:

  • AWS Systems Manager Parameter Store
  • AWS Secrets Manager

Details on passing secrets or sensitive information securely to containers in an AWS ECS task can be found here.

  1. Locate the secret within the value of the launch configuration UserData
  2. Consider your options of moving the embedded secret to a more secure location such as described above
  3. Make the move
  4. Test it
  5. Ship it 🚢 and relax 🌴