Insecure Use of Cryptography
Why is this important?โ
Cryptography is hard. And when it is used in an application, it's usually to make sure user data is secure in transit and at rest. Cryptographic libraries are not always easy to use and can even contain insecurities. They often require the Developer to have a good understanding of the primitives available and expect the Developer to make the right choices. A great cryptographic library has minimal knobs and dials and uses the best cryptographic primitives by default thus freeing the Developer from having to understand the primitives and make the right decisions.
Check out this video for a high-level explanation:
ELB Using Weak Ciphersโ
ELB Predefined or Custom Security Policies must not use weak ciphers, to reduce the risk of the SSL connection between the client and the load balancer being exploited. This means that the name
of the policy_attribute
must not coincide with any of a predefined list of weak ciphers.
Option A: Locate out-of-date (known weak) cipher or policy and replace it with a strong cipher or policyโ
- Review the value of
aws_load_balancer_policy
policy_attribute.name
. The value should be set to one of the known secure TLS ciphers. The default value (if not visibly present) ofpolicy_attribute.name
uses a known good TLS cipher - If an out of date (less than optimal) cipher is being used replace it with a good one
Detailed Instructionsโ
Locate one of the following vulnerable patterns:
resource "aws_load_balancer_policy" "positive1" {
load_balancer_name = aws_elb.wu-tang.name
policy_name = "wu-tang-ssl"
policy_type_name = "SSLNegotiationPolicyType"
policy_attribute {
name = "Protocol-TLSv1.2"
value = "true"
}
policy_attribute {
// Weak cipher.
name = "TLS_RSA_ARCFOUR_128_SHA1"
value = "true"
}
}
resource "aws_load_balancer_policy" "positive2" {
load_balancer_name = aws_elb.wu-tang.name
policy_name = "wu-tang-ssl"
policy_type_name = "SSLNegotiationPolicyType"
policy_attribute {
// Weak cipher.
name = "DES-CBC3-SHA"
value = "true"
}
}
resource "aws_load_balancer_policy" "positive3" {
load_balancer_name = aws_elb.wu-tang.name
policy_name = "wu-tang-ssl"
policy_type_name = "SSLNegotiationPolicyType"
policy_attribute {
// Weak cipher.
name = "TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384"
value = "true"
}
}Modify the config to something like one of the following:
resource "aws_load_balancer_policy" "negative1" {
load_balancer_name = aws_elb.wu-tang.name
policy_name = "wu-tang-ssl"
policy_type_name = "SSLNegotiationPolicyType"
policy_attribute {
// Strong cipher.
name = "ECDHE-ECDSA-AES128-GCM-SHA256"
value = "true"
}
policy_attribute {
// Strong policy.
name = "Protocol-TLSv1.2"
value = "true"
}
}
resource "aws_load_balancer_policy" "negative2" {
load_balancer_name = aws_elb.wu-tang.name
policy_name = "wu-tang-ssl"
policy_type_name = "SSLNegotiationPolicyType"
policy_attribute {
// Acceptable policy.
name = "Reference-Security-Policy"
value = "ELBSecurityPolicy-TLS-1-1-2017-01"
}
}Test it
Ship it ๐ข and relax ๐ด
References:โ
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โ
Go through the issues that GuardRails identified
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
}Test it
Ship it ๐ข and relax ๐ด
Missing Server Side Encryptionโ
AWS allows to leverage 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โ
Go through the issues that GuardRails identified
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"
}
}
}
}Test it
Ship it ๐ข and relax ๐ด
Secure Ciphers Disabledโ
Check if secure ciphers aren't used in AWS CloudFront.
Option A: Make sure the Minimum Protocol Version is not out of date and the default certificate is trueโ
- The
aws_cloudfront_distribution
viewer_certificate.minimum_protocol_version
should be at least "TLSv1.1" but preferably more recent - The
aws_cloudfront_distribution
viewer_certificate.cloudfront_default_certificate
should be true
Detailed Instructionsโ
Locate the following vulnerable pattern:
resource "aws_cloudfront_distribution" "positive1" {
origin {
domain_name = "mybucket"
origin_id = "myS3Origin"
s3_origin_config {
origin_access_identity = "origin-access-identity/cloudfront/ABCDEFG1234567"
}
}
enabled = true
default_cache_behavior {
allowed_methods = ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"]
cached_methods = ["GET", "HEAD"]
target_origin_id = "myS3Origin"
forwarded_values {
query_string = false
cookies {
forward = "none"
}
}
viewer_protocol_policy = "allow-all"
min_ttl = 0
default_ttl = 3600
max_ttl = 86400
}
restrictions {
geo_restriction {
restriction_type = "whitelist"
locations = ["US", "CA", "GB", "DE"]
}
}
viewer_certificate {
// Vulnerable pattern: Viewers don't have to use HTTPS to request your objects.
cloudfront_default_certificate = false
// Protocol version too low.
minimum_protocol_version = "SSLv3"
}
}Modify the config to something like the following:
resource "aws_cloudfront_distribution" "negative1" {
origin {
domain_name = "mybucket"
origin_id = "myS3Origin"
s3_origin_config {
origin_access_identity = "origin-access-identity/cloudfront/ABCDEFG1234567"
}
}
enabled = true
default_cache_behavior {
allowed_methods = ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"]
cached_methods = ["GET", "HEAD"]
target_origin_id = "myS3Origin"
forwarded_values {
query_string = false
cookies {
forward = "none"
}
}
viewer_protocol_policy = "allow-all"
min_ttl = 0
default_ttl = 3600
max_ttl = 86400
}
restrictions {
geo_restriction {
restriction_type = "whitelist"
locations = ["US", "CA", "GB", "DE"]
}
}
viewer_certificate {
// Viewers must use HTTPS to request your objects.
cloudfront_default_certificate = true
// Protocol version starts with TLSv1.2
minimum_protocol_version = "TLSv1.2_2019"
}
}Test it
Ship it ๐ข and relax ๐ด
References:โ
Storage Account Not Using Latest TLS Encryption Versionโ
Ensure Storage Account is using the latest version of TLS encryption.
Option A: Make sure the Minimum Storage Account TLS Version is set correctlyโ
The azurerm_storage_account
min_tls_version
Should be defined and have a value of at least "TLS1_2". If the min_tls_version
is not defined, new storage accounts will default to "TLS1_2" which is actually good, but will incorrectly fail this rule. To work around this simply be specific about the min_tls_version
.
Detailed Instructionsโ
Locate one of the following vulnerable patterns:
resource "azurerm_storage_account" "positive1" {
name = "storageaccountname"
resource_group_name = azurerm_resource_group.example.name
location = azurerm_resource_group.example.location
account_tier = "Standard"
account_replication_type = "GRS"
// Vulnerable.
min_tls_version = "TLS1_1"
tags = {
environment = "staging"
}
}Modify the config to something like the following:
resource "azurerm_storage_account" "negative1" {
name = "storageaccountname"
resource_group_name = azurerm_resource_group.example.name
location = azurerm_resource_group.example.location
account_tier = "Standard"
account_replication_type = "GRS"
// Not Vulnerable.
min_tls_version = "TLS1_2"
tags = {
environment = "staging"
}
}Test it
Ship it ๐ข and relax ๐ด
References:โ
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:
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.
Go through the issues that GuardRails identified
Identify the affected block devices:
ebs_block_device = [{
device_name = "/dev/sdf"
volume_type = "gp2"
volume_size = 100
encrypted = false
}]Modify the
encrypted
argument totrue
Test it
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.
Go through the issues that GuardRails identified
Identify the affected
azurerm_managed_disk
resourcesresource "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"
}Ensure that the
encryption_settings
are configured properlyresource "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.
Go through the issues that GuardRails identified
Identify the affected
azurerm_data_lake_store
resourcesresource "azurerm_data_lake_store" "example" {
name = "consumptiondatalake"
resource_group_name = azurerm_resource_group.example.name
location = azurerm_resource_group.example.location
encryption_state = "Disabled"
}Ensure that the
encryption_state
is configured properlyresource "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.
Go through the issues that GuardRails identified
Identify the affected
google_compute_disk
resourcesresource "google_compute_disk" "default" {
name = "test-disk"
type = "pd-ssd"
zone = "us-central1-a"
image = "debian-8-jessie-v20170523"
}Ensure that the
disk_encryption_key
block is configured properlyresource "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โ
Go through the issues that GuardRails identified
Identify the affected
google_storage_bucket
resourcesresource "google_storage_bucket" "static-site" {
name = "image-store.com"
location = "EU"
force_destroy = true
}Ensure that the
encryption
block is set and configured properlyresource "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}"
}
}
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.
Option A: Make sure EC2 Launch Configuration User Data does not contain encoded RSA Private Keyโ
If one of the following contains an encoded RSA private key:
aws_launch_configuration
user_data_base64
module
user_data_base64
Move it to a location that stores secret values in AWS such as the following:
- AWS Systems Manager Parameter Store
- AWS Secrets Manager
Detailed Instructionsโ
Locate one of the following vulnerable patterns:
Vulnerable
resource
aws_launch_configuration
user_data_base64
contains private key pattern:resource "aws_launch_configuration" "positive1" {
image_id = data.aws_ami.ubuntu.id
instance_type = "m4.large"
spot_price = "0.001"
user_data_base64 = "LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpzb21lS2V5" # someKey
lifecycle {
create_before_destroy = true
}
}Vulnerable
module
user_data_base64
contains private key pattern:module "positive2" {
source = "terraform-aws-modules/autoscaling/aws"
version = "1.0.4"
# Launch configuration
lc_name = "example-lc"
image_id = "ami-ebd02392"
instance_type = "t2.micro"
security_groups = ["sg-12345678"]
user_data_base64 = "LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpzb21lS2V5"
ebs_block_device = [
{
device_name = "/dev/xvdz"
volume_type = "gp2"
volume_size = "50"
delete_on_termination = true
},
]
root_block_device = [
{
volume_size = "50"
volume_type = "gp2"
},
]
# Auto scaling group
asg_name = "example-asg"
vpc_zone_identifier = ["subnet-1235678", "subnet-87654321"]
health_check_type = "EC2"
min_size = 0
max_size = 1
desired_capacity = 1
wait_for_capacity_timeout = 0
tags = [
{
key = "Environment"
value = "dev"
propagate_at_launch = true
},
{
key = "Project"
value = "megasecret"
propagate_at_launch = true
},
]
}Vulnerable
module
user_data_base64
contains private key pattern:module "positive3" {
source = "terraform-aws-modules/autoscaling/aws"
version = "1.0.4"
# Launch configuration
lc_name = "example-lc"
image_id = "ami-ebd02392"
instance_type = "t2.micro"
security_groups = ["sg-12345678"]
user_data_base64 = "LS0tLS1CRUdJTiBPUEVOU1NIIFBSSVZBVEUgS0VZIEJMT0NLLS0tLS0="
ebs_block_device = [
{
device_name = "/dev/xvdz"
volume_type = "gp2"
volume_size = "50"
delete_on_termination = true
},
]
root_block_device = [
{
volume_size = "50"
volume_type = "gp2"
},
]
# Auto scaling group
asg_name = "example-asg"
vpc_zone_identifier = ["subnet-1235678", "subnet-87654321"]
health_check_type = "EC2"
min_size = 0
max_size = 1
desired_capacity = 1
wait_for_capacity_timeout = 0
tags = [
{
key = "Environment"
value = "dev"
propagate_at_launch = true
},
{
key = "Project"
value = "megasecret"
propagate_at_launch = true
},
]
}Modify the config to something like the following:
Replacement
resource
aws_launch_configuration
with nouser_data_base64
defined pattern:resource "aws_launch_configuration" "negative1" {
image_id = data.aws_ami.ubuntu.id
instance_type = "m4.large"
spot_price = "0.001"
lifecycle {
create_before_destroy = true
}
}Replacement
resource
aws_launch_configuration
with emptyuser_data_base64
pattern:resource "aws_launch_configuration" "negative2" {
image_id = data.aws_ami.ubuntu.id
instance_type = "m4.large"
spot_price = "0.001"
user_data_base64 = ""
lifecycle {
create_before_destroy = true
}
}Replacement
resource
aws_launch_configuration
user_data_base64
containing non-vulnerable pattern:resource "aws_launch_configuration" "negative3" {
image_id = data.aws_ami.ubuntu.id
instance_type = "m4.large"
spot_price = "0.001"
user_data_base64 = "dGVzdA=="
lifecycle {
create_before_destroy = true
}
}Replacement
resource
aws_launch_configuration
user_data_base64
containing null pattern:resource "aws_launch_configuration" "negative4" {
image_id = data.aws_ami.ubuntu.id
instance_type = "m4.large"
spot_price = "0.001"
user_data_base64 = null
lifecycle {
create_before_destroy = true
}
}Replacement
module
with nouser_data_base64
defined pattern:module "asg" {
source = "terraform-aws-modules/autoscaling/aws"
version = "1.0.4"
# Launch configuration
lc_name = "example-lc"
image_id = "ami-ebd02392"
instance_type = "t2.micro"
security_groups = ["sg-12345678"]
ebs_block_device = [
{
device_name = "/dev/xvdz"
volume_type = "gp2"
volume_size = "50"
delete_on_termination = true
},
]
root_block_device = [
{
volume_size = "50"
volume_type = "gp2"
},
]
# Auto scaling group
asg_name = "example-asg"
vpc_zone_identifier = ["subnet-1235678", "subnet-87654321"]
health_check_type = "EC2"
min_size = 0
max_size = 1
desired_capacity = 1
wait_for_capacity_timeout = 0
tags = [
{
key = "Environment"
value = "dev"
propagate_at_launch = true
},
{
key = "Project"
value = "megasecret"
propagate_at_launch = true
},
]
}Replacement
module
with emptyuser_data_base64
pattern:module "asg" {
source = "terraform-aws-modules/autoscaling/aws"
version = "1.0.4"
# Launch configuration
lc_name = "example-lc"
image_id = "ami-ebd02392"
instance_type = "t2.micro"
security_groups = ["sg-12345678"]
user_data_base64 = ""
ebs_block_device = [
{
device_name = "/dev/xvdz"
volume_type = "gp2"
volume_size = "50"
delete_on_termination = true
},
]
root_block_device = [
{
volume_size = "50"
volume_type = "gp2"
},
]
# Auto scaling group
asg_name = "example-asg"
vpc_zone_identifier = ["subnet-1235678", "subnet-87654321"]
health_check_type = "EC2"
min_size = 0
max_size = 1
desired_capacity = 1
wait_for_capacity_timeout = 0
tags = [
{
key = "Environment"
value = "dev"
propagate_at_launch = true
},
{
key = "Project"
value = "megasecret"
propagate_at_launch = true
},
]
}Replacement
module
user_data_base64
containing non-vulnerable pattern:module "asg" {
source = "terraform-aws-modules/autoscaling/aws"
version = "1.0.4"
# Launch configuration
lc_name = "example-lc"
image_id = "ami-ebd02392"
instance_type = "t2.micro"
security_groups = ["sg-12345678"]
user_data_base64 = "dGVzdA=="
ebs_block_device = [
{
device_name = "/dev/xvdz"
volume_type = "gp2"
volume_size = "50"
delete_on_termination = true
},
]
root_block_device = [
{
volume_size = "50"
volume_type = "gp2"
},
]
# Auto scaling group
asg_name = "example-asg"
vpc_zone_identifier = ["subnet-1235678", "subnet-87654321"]
health_check_type = "EC2"
min_size = 0
max_size = 1
desired_capacity = 1
wait_for_capacity_timeout = 0
tags = [
{
key = "Environment"
value = "dev"
propagate_at_launch = true
},
{
key = "Project"
value = "megasecret"
propagate_at_launch = true
},
]
}Replacement
module
user_data_base64
containing null pattern:module "asg" {
source = "terraform-aws-modules/autoscaling/aws"
version = "1.0.4"
# Launch configuration
lc_name = "example-lc"
image_id = "ami-ebd02392"
instance_type = "t2.micro"
security_groups = ["sg-12345678"]
user_data_base64 = null
ebs_block_device = [
{
device_name = "/dev/xvdz"
volume_type = "gp2"
volume_size = "50"
delete_on_termination = true
},
]
root_block_device = [
{
volume_size = "50"
volume_type = "gp2"
},
]
# Auto scaling group
asg_name = "example-asg"
vpc_zone_identifier = ["subnet-1235678", "subnet-87654321"]
health_check_type = "EC2"
min_size = 0
max_size = 1
desired_capacity = 1
wait_for_capacity_timeout = 0
tags = [
{
key = "Environment"
value = "dev"
propagate_at_launch = true
},
{
key = "Project"
value = "megasecret"
propagate_at_launch = true
},
]
}Test it
Ship it ๐ข and relax ๐ด