Skip to main content

Insecure Use of Cryptography

Fixing insecure algorithms and cipher modes

About insecure algorithms and cipher modes

What are insecure algorithms and cipher modes?

A cryptographic algorithm and a cipher mode are two different concepts used in cryptography.

A cryptographic algorithm is a mathematical function used to encrypt or decrypt data. It defines the rules for transforming plaintext (unencrypted) data into ciphertext (encrypted) data, and vice versa. Common cryptographic algorithms include Advanced Encryption Standard (AES), RSA, and Triple Data Encryption Standard (3DES).

On the other hand, a cipher mode is a method of applying a cryptographic algorithm to encrypt or decrypt data. It defines the way in which plaintext is broken into blocks and how these blocks are transformed into ciphertext. Common cipher modes include Electronic Codebook (ECB), Cipher Block Chaining (CBC), and Galois/Counter Mode (GCM).

The difference between a cryptographic algorithm and a cipher mode is that an algorithm defines the mathematical rules for encryption and decryption, while a cipher mode defines the specific way in which these rules are applied to transform plaintext into ciphertext.

A cryptographic algorithm is a fundamental building block of cryptography, while a cipher mode provides additional security features and determines how data is processed.

Insecure algorithms are cryptographic algorithms that are known to have vulnerabilities that can be exploited by attackers. Cryptographic algorithms are used in security systems to protect data.

An example of an insecure algorithm is the Data Encryption Standard (DES), which is vulnerable to brute-force attacks.

Insecure cipher modes are cryptographic modes that have vulnerabilities or weaknesses that can be exploited by attackers to compromise the security of the encryption. The use of insecure cipher modes can result in data being decrypted or tampered with by unauthorized parties, which can lead to serious security breaches and data leaks.

Some examples of insecure cipher modes include:

  • Electronic Codebook (ECB): ECB mode is insecure because it encrypts each block of plaintext independently, which can lead to patterns in the ciphertext that reveal information about the plaintext.
  • Cipher Block Chaining (CBC) with a static IV: CBC mode with a static initialization vector (IV) is vulnerable to chosen plaintext attacks, where an attacker can manipulate the plaintext and observe the resulting ciphertext to learn more about the encryption algorithm.
  • Cipher Feedback (CFB) mode with a small segment size: CFB mode with a small segment size can be vulnerable to bit-flipping attacks, where an attacker can manipulate the ciphertext to change the decrypted plaintext.
  • Stream cipher modes using weak key schedules: Some stream cipher modes use weak key schedules that can be easily broken by attackers, allowing them to decrypt the ciphertext and gain access to sensitive data.

Check out this video for a high-level explanation:

What is the impact of insecure algorithms and cipher modes?

Insecure algorithms in security systems can have significant impacts on the security and privacy of data.

Here are some of the potential impacts:

  • Data breaches: Insecure algorithms and cipher modes can be exploited by attackers to decrypt or tamper with encrypted data, leading to data breaches and the exposure of sensitive information.
  • Data loss: In some cases, the use of insecure algorithms and cipher modes can result in the loss of encrypted data, either through accidental deletion or malicious tampering by attackers.
  • Compliance violations: The use of insecure algorithms and cipher modes can lead to compliance violations with industry standards and regulations, such as the Payment Card Industry Data Security Standard (PCI DSS) or the General Data Protection Regulation (GDPR).
  • Reputation damage: In the event of a data breach or other security incident caused by insecure algorithms and cipher modes, organizations may suffer reputational damage, loss of customer trust, and legal or financial penalties.

How to prevent insecure algorithms and cipher modes?

Several measures can prevent the use of insecure algorithms, including:

  • Use strong cryptographic algorithms: Use strong and up-to-date cryptographic algorithms that have been widely tested and validated by security experts. For example, Advanced Encryption Standard (AES) encryption algorithm is widely used and has been proven to be secure.
  • Disable or remove insecure algorithms: Disable or remove insecure algorithms, such as DES or RC4, from systems and applications.
  • Use well-designed cipher modes: Use well-designed cipher modes that provide strong security guarantees, such as Cipher Block Chaining (CBC) with randomized initialization vectors (IVs) or Galois/Counter Mode (GCM).
  • Avoid using weak cipher modes: Avoid using insecure cipher modes such as Electronic Codebook (ECB) or Cipher Feedback (CFB) mode with a small segment size.
  • Regularly update cryptographic libraries and dependencies: Keep all cryptographic libraries and dependencies up-to-date with the latest security patches and updates.
  • Regularly review and update security policies and procedures: Regularly review and update security policies and procedures to ensure that they remain up-to-date with the latest best practices and standards.

References

Taxonomies

Explanation & Prevention

Training

Missing Server Side Encryption

AWS allows leveraging server-side encryption for SQS queues, SNS topics and S3 buckets, which is considered a security best practice. For example, when server-side encryption is used for S3, an object is encrypted before saving it to disk and decrypted when it is downloaded.

Option A: Enable Server Side Encryption

  1. Go through the issues that GuardRails identified

  2. Change the resources to use server-side encryption

    # SQS queue example
    resource "aws_sqs_queue" "terraform_queue" {
    name = "terraform-example-queue"
    kms_master_key_id = "alias/aws/sqs"
    kms_data_key_reuse_period_seconds = 300
    }

    # SNS topic example
    resource "aws_sns_topic" "user_updates" {
    name = "user-updates-topic"
    kms_master_key_id = "alias/aws/sns"
    }

    # S3 bucket example

    resource "aws_kms_key" "mykey" {
    description = "This key is used to encrypt bucket objects"
    deletion_window_in_days = 10
    }

    resource "aws_s3_bucket" "mybucket" {
    bucket = "mybucket"

    server_side_encryption_configuration {
    rule {
    apply_server_side_encryption_by_default {
    kms_master_key_id = aws_kms_key.mykey.arn
    sse_algorithm = "aws:kms"
    }
    }
    }
    }
  3. Test it

  4. Ship it 🚢 and relax 🌴

Unencrypted Data Storage

Option A: Ensure AWS block devices are encrypted at rest

AWS offers block devices to store data for AWS instances. There are two types:

  1. Root Block Devices
  2. EBS Block Devices

Root block devices are the main disk for an instance, and EBS block instances are additional disks that can be used for storage.

Block devices can be encrypted to provide better security.

  1. Go through the issues that GuardRails identified

  2. Identify the affected block devices:

    ebs_block_device = [{
    device_name = "/dev/sdf"
    volume_type = "gp2"
    volume_size = 100
    encrypted = false
    }]
  3. Modify the encrypted argument to true

  4. Test it

  5. Ship it 🚢 and relax 🌴

Option B: Ensure Azure disks are encrypted at rest

Azure offers managed disks to store data. These disks can be encrypted to provide enhanced security.

  1. Go through the issues that GuardRails identified

  2. Identify the affected azurerm_managed_disk resources

    resource "azurerm_managed_disk" "example" {
    name = "acctestmd"
    location = "West US 2"
    resource_group_name = azurerm_resource_group.example.name
    storage_account_type = "Standard_LRS"
    create_option = "Empty"
    disk_size_gb = "1"
    }
  3. Ensure that the encryption_settings are configured properly

    resource "azurerm_managed_disk" "example" {
    name = "acctestmd"
    location = "West US 2"
    resource_group_name = azurerm_resource_group.example.name
    storage_account_type = "Standard_LRS"
    create_option = "Empty"
    disk_size_gb = "1"
    encryption_settings = "enabled"
    }

Option C: Ensure Azure Data Lakes are encrypted at rest

Azure offers managed data lakes to store data, which support encryption at rest to provide enhanced security.

  1. Go through the issues that GuardRails identified

  2. Identify the affected azurerm_data_lake_store resources

    resource "azurerm_data_lake_store" "example" {
    name = "consumptiondatalake"
    resource_group_name = azurerm_resource_group.example.name
    location = azurerm_resource_group.example.location
    encryption_state = "Disabled"
    }
  3. Ensure that the encryption_state is configured properly

    resource "azurerm_data_lake_store" "example" {
    name = "consumptiondatalake"
    resource_group_name = azurerm_resource_group.example.name
    location = azurerm_resource_group.example.location
    encryption_state = "Enabled"
    encryption_type = "ServiceManaged"
    }

Option D: Ensure GCP disks are encrypted at rest

GCP offers managed disks to store data. These disks can be encrypted to provide enhanced security.

  1. Go through the issues that GuardRails identified

  2. Identify the affected google_compute_disk resources

    resource "google_compute_disk" "default" {
    name = "test-disk"
    type = "pd-ssd"
    zone = "us-central1-a"
    image = "debian-8-jessie-v20170523"

    }
  3. Ensure that the disk_encryption_key block is configured properly

    resource "google_compute_disk" "default" {
    name = "test-disk"
    type = "pd-ssd"
    zone = "us-central1-a"
    image = "debian-8-jessie-v20170523"
    disk_encryption_key {
    kms_key_self_link = "${var.encryption_key}"
    }
    }

Option E: Ensure GCP buckets are encrypted at rest

  1. Go through the issues that GuardRails identified

  2. Identify the affected google_storage_bucket resources

    resource "google_storage_bucket" "static-site" {
    name = "image-store.com"
    location = "EU"
    force_destroy = true

    }
  3. Ensure that the encryption block is set and configured properly

    resource "google_storage_bucket" "static-site" {
    name = "image-store.com"
    location = "EU"
    force_destroy = true
    encryption {
    default_kms_key_name = "${google_kms_crypto_key.bucket_key.self_link}"
    }
    }

RDS Storage Not Encrypted

This rule detects that the cluster Storage isn't encrypted, which is the case when storage_encrypted is not set to true.

Rule-specific references:

Option A: Make sure Storage Encrypted is set to true

resource aws_rds_cluster storage_encrypted should have its value set to true whether by default or being specific. Other properties of aws_rds_cluster affect what the default value of storage_encrypted is, so be sure to read the Terraform documentation.

  1. Locate the following vulnerable pattern:

    Vulnerable explicit storage_encrypted false pattern:

    resource "aws_rds_cluster" "positive3" {
    cluster_identifier = "cloudrail-test-non-encrypted"
    engine = "aurora-mysql"
    engine_version = "5.7.mysql_aurora.2.03.2"
    availability_zones = ["eu-west-1a", "eu-west-1b", "eu-west-1c"]
    database_name = "cloudrail"
    master_username = "administrator"
    master_password = "cloudrail-TEST-password"
    skip_final_snapshot = true
    storage_encrypted = false
    }

    Vulnerable implicit storage_encrypted false pattern:

    resource "aws_rds_cluster" "positive1" {
    cluster_identifier = "example"
    engine = "aurora-mysql"
    engine_version = "5.7.mysql_aurora.2.03.2"
    availability_zones = ["us-west-2a", "us-west-2b", "us-west-2c"]
    database_name = "mydb"
    master_username = "foo"
    master_password = "bar"
    backup_retention_period = 5
    preferred_backup_window = "07:00-09:00"
    }
  2. Modify the config to something like one of the following:

    Replacement explicit storage_encrypted true pattern:

    resource "aws_rds_cluster" "negative1" {
    cluster_identifier = "cloudrail-test-non-encrypted"
    engine = "aurora-mysql"
    engine_version = "5.7.mysql_aurora.2.03.2"
    availability_zones = ["eu-west-1a", "eu-west-1b", "eu-west-1c"]
    database_name = "cloudrail"
    master_username = "administrator"
    master_password = "cloudrail-TEST-password"
    skip_final_snapshot = true
    storage_encrypted = true
    }

    Replacement implicit storage_encrypted true pattern:

    resource "aws_rds_cluster" "negative2" {
    cluster_identifier = "example"
    engine = "aurora-mysql"
    engine_version = "5.7.mysql_aurora.2.03.2"
    // storage_encrypted defaults to true for engine_mode of serverless
    engine_mode = "serverless"
    availability_zones = ["eu-west-1a", "eu-west-1b", "eu-west-1c"]
    database_name = "cloudrail"
    master_username = "administrator"
    master_password = "cloudrail-TEST-password"
    }
  3. Test it

  4. Ship it 🚢 and relax 🌴

S3 Bucket Object Not Encrypted

S3 Bucket Object should have server-side encryption enabled.

Rule-specific references:

Option A: AWS S3 Bucket Object Server Side Encryption must be defined and not null

aws_s3_bucket_object server_side_encryption must be defined and not null.

  1. Locate the following vulnerable pattern:

    resource "aws_s3_bucket" "examplebucket" {
    bucket = "examplebuckettftest"
    acl = "private"

    versioning {
    enabled = true
    }

    object_lock_configuration {
    object_lock_enabled = "Enabled"
    }
    }

    resource "aws_s3_bucket_object" "examplebucket_object" {
    key = "someobject"
    bucket = aws_s3_bucket.examplebucket.id
    source = "index.html"
    }
  2. Modify the config to something like the following:

    resource "aws_s3_bucket" "examplebucket" {
    bucket = "examplebuckettftest"
    acl = "private"

    versioning {
    enabled = true
    }

    object_lock_configuration {
    object_lock_enabled = "Enabled"
    }
    }

    resource "aws_s3_bucket_object" "examplebucket_object" {
    key = "someobject"
    bucket = aws_s3_bucket.examplebucket.id
    source = "index.html"
    server_side_encryption = "AES256"
    }
  3. Test it

  4. Ship it 🚢 and relax 🌴

S3 Bucket SSE Disabled

If the algorithm is AES256 then the master key is null, empty, or undefined, otherwise the master key is required.

Rule-specific references:

Option A: Make sure S3 Bucket Server Side Encryption is enabled

There are several options for server-side encryption depending on your threat model.

  1. Locate one of the following vulnerable patterns:

    Vulnerable resource pattern server_side_encryption_configuration should be defined and not null:

    resource "aws_s3_bucket" "positive1" {
    bucket = "my-tf-test-bucket"
    acl = "private"

    tags = {
    Name = "My bucket"
    Environment = "Dev"
    }

    versioning {
    mfa_delete = true
    }
    }

    Vulnerable resource pattern kms_master_key_id should be null when algorithm is "AES256":

    resource "aws_s3_bucket" "positive1" {
    bucket = "my-tf-test-bucket"
    acl = "private"

    tags = {
    Name = "My bucket"
    Environment = "Dev"
    }

    server_side_encryption_configuration {
    rule {
    apply_server_side_encryption_by_default {
    kms_master_key_id = "some-key"
    sse_algorithm = "AES256"
    }
    }
    }

    versioning {
    mfa_delete = true
    }
    }

    Vulnerable resource pattern sse_algorithm should be "AES256" when key is null:

    resource "aws_s3_bucket" "positive1" {
    bucket = "my-tf-test-bucket"
    acl = "private"

    tags = {
    Name = "My bucket"
    Environment = "Dev"
    }

    server_side_encryption_configuration {
    rule {
    apply_server_side_encryption_by_default {
    sse_algorithm = "aws:kms"
    }
    }
    }

    versioning {
    mfa_delete = true
    }
    }

    Vulnerable module pattern server_side_encryption_configuration should be defined and not null:

    module "s3_bucket" {
    source = "terraform-aws-modules/s3-bucket/aws"
    version = "3.7.0"

    bucket = "my-s3-bucket"
    acl = "private"

    versioning = {
    enabled = true
    }

    }

    Vulnerable module pattern kms_master_key_id should be null when algorithm is "AES256":

    module "s3_bucket" {
    source = "terraform-aws-modules/s3-bucket/aws"
    version = "3.7.0"

    bucket = "my-s3-bucket"
    acl = "private"

    versioning = {
    enabled = true
    }

    server_side_encryption_configuration {
    rule {
    apply_server_side_encryption_by_default {
    kms_master_key_id = "some-key"
    sse_algorithm = "AES256"
    }
    }
    }
    }

    Vulnerable module pattern sse_algorithm should be "AES256" when key is null:

    module "s3_bucket" {
    source = "terraform-aws-modules/s3-bucket/aws"
    version = "3.7.0"

    bucket = "my-s3-bucket"
    acl = "private"

    versioning = {
    enabled = true
    }

    server_side_encryption_configuration {
    rule {
    apply_server_side_encryption_by_default {
    sse_algorithm = "aws:kms"
    }
    }
    }
    }
  2. Modify the config to something like one of the following:

    Replacement resource pattern:

    resource "aws_s3_bucket" "negative1" {
    bucket = "my-tf-test-bucket"
    acl = "private"

    tags = {
    Name = "My bucket"
    Environment = "Dev"
    }

    server_side_encryption_configuration {
    rule {
    apply_server_side_encryption_by_default {
    kms_master_key_id = aws_kms_key.mykey.arn
    sse_algorithm = "aws:kms"
    }
    }
    }

    versioning {
    mfa_delete = true
    }
    }

    Replacement module pattern:

    module "s3_bucket" {
    source = "terraform-aws-modules/s3-bucket/aws"
    version = "3.7.0"

    bucket = "my-s3-bucket"
    acl = "private"

    versioning = {
    enabled = true
    }

    server_side_encryption_configuration {
    rule {
    apply_server_side_encryption_by_default {
    kms_master_key_id = aws_kms_key.mykey.arn
    sse_algorithm = "aws:kms"
    }
    }
    }
    }
  3. Test it

  4. Ship it 🚢 and relax 🌴

Missing Cryptographic Key Auto Rotation

AWS KMS makes secret management easy, however, there are additional considerations to further secure the customer master keys. AWS KMS allows key rotation, which changes the backing key and provides a couple of benefits. For more information see the key rotation. Note that changing this setting won't have any impact on the encrypted data.

Option A: Enable Key Rotation

  1. Go through the issues that GuardRails identified

  2. Change the master key resource as shown below:

    resource "aws_kms_key" "a" {
    description = "KMS key 1"
    deletion_window_in_days = 10
    enable_key_rotation = true
    }
  3. Test it

  4. Ship it 🚢 and relax 🌴