Insecure encryption algorithm - Default encryption - Ruby

Insecure encryption algorithm - Default encryption - Ruby

Need

Implementation of Customer Controlled Keys (CMK) for encryption

Context

  • Usage of Ruby for building dynamic and object-oriented applications
  • Usage of aws-sdk for interacting with Amazon Web Services (AWS) services

Description

Non compliant code

        require 'aws-sdk'

s3 = Aws::S3::Client.new(
  region: 'us-west-2',
  access_key_id: 'AKIAIOSFODNN7EXAMPLE',
  secret_access_key: 'wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY'
)

# Create a new S3 bucket with default key
s3.create_bucket({
  bucket: 'mybucket',
  create_bucket_configuration: {
    location_constraint: 'us-west-2'
  }
})

# Upload a file to the new S3 bucket using default key
File.open('myfile.txt', 'rb') do |file|
  s3.put_object({
    bucket: 'mybucket',
    key: 'myfile.txt',
    body: file
  })
end
        
        

In the above Ruby code snippet, we are using the AWS SDK to interact with Amazon S3 service. We are creating a new bucket and uploading a file to this bucket. However, the issue here is that we are using the default encryption key provided by AWS for our S3 bucket.

The potential vulnerability lies in the fact that the default encryption keys are managed by AWS, which means we don't have full control over them. If the default keys were to be compromised, our data could be at risk.

In this scenario, it's better to use Customer Managed Keys (CMKs) with AWS Key Management Service (KMS). CMKs give us more control over the cryptographic keys and we can establish and enforce our own key management policies.

Steps

  • Use a secure encryption algorithm instead of the default encryption algorithm provided by AWS SDK.
  • Generate and use a Customer Master Key (CMK) for encryption.
  • Configure the AWS SDK to use the CMK for encryption.
  • Update the code to create the S3 bucket and upload files using the CMK for encryption.

Compliant code

        require 'aws-sdk'

kms = Aws::KMS::Client.new(
  region: 'us-west-2',
  access_key_id: 'AKIAIOSFODNN7EXAMPLE',
  secret_access_key: 'wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY'
)

# Create a new CMK
cmk = kms.create_key({
  description: 'My CMK',
  key_usage: 'ENCRYPT_DECRYPT',
  origin: 'AWS_KMS'
})

s3 = Aws::S3::Client.new(
  region: 'us-west-2',
  access_key_id: 'AKIAIOSFODNN7EXAMPLE',
  secret_access_key: 'wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY'
)

# Create a new S3 bucket with CMK
s3.create_bucket({
  bucket: 'mybucket',
  create_bucket_configuration: {
    location_constraint: 'us-west-2'
  }
})

# Upload a file to the new S3 bucket using CMK
File.open('myfile.txt', 'rb') do |file|
  s3.put_object({
    bucket: 'mybucket',
    key: 'myfile.txt',
    body: file,
    server_side_encryption: 'aws:kms',
    ssekms_key_id: cmk.key_metadata.key_id
  })
end
        
        

The above code first creates a new Customer Master Key (CMK) using the AWS Key Management Service (KMS). This CMK is then used to encrypt the data stored in the S3 bucket.

The create_key method is used to create a new CMK. The description parameter is used to provide a description for the CMK. The key_usage parameter is set to 'ENCRYPT_DECRYPT' to allow the CMK to be used for both encryption and decryption. The origin parameter is set to 'AWS_KMS' to specify that the CMK is created within AWS KMS.

The put_object method is used to upload a file to the S3 bucket. The server_side_encryption parameter is set to 'aws:kms' to specify that AWS KMS is used for server-side encryption. The ssekms_key_id parameter is set to the ID of the CMK to specify that the CMK is used for encryption.

This way, the data stored in the S3 bucket is encrypted using a secure encryption algorithm provided by the CMK, instead of the default encryption algorithm provided by the AWS SDK.

References