Skip to main content

Insecure encryption algorithm - Default encryption

Need

Implementation of customer-controlled keys for encryption

Context

  • Usage of C# for building robust and scalable applications
  • Usage of Amazon S3 for storing and retrieving files in the cloud
  • Usage of System for accessing system-level functionality and resources
  • Usage of System.Threading.Tasks for asynchronous programming in .NET

Description

Non compliant code

using Amazon.S3;
using Amazon.S3.Model;
using System;
using System.Threading.Tasks;

public class S3Encryption
{
private static readonly string bucketName = "your-aws-bucket";
private static readonly string keyName = "your-object-key";
private static IAmazonS3 s3Client;

public static void Main()
{
s3Client = new AmazonS3Client(Amazon.RegionEndpoint.USWest2);
Console.WriteLine("Encrypting an object and uploading to bucket.\\n");
EncryptingAnObjectAsync().Wait();
}

static async Task EncryptingAnObjectAsync()
{
try
{
var putRequest = new PutObjectRequest
{
BucketName = bucketName,
Key = keyName,
ContentBody = "This is the body of the S3 object.",
ServerSideEncryptionMethod = ServerSideEncryptionMethod.AES256
};

await s3Client.PutObjectAsync(putRequest);
}
catch (AmazonS3Exception e)
{
Console.WriteLine("Error encountered on server. Message:'{0}' when writing an object", e.Message);
}
catch (Exception e)
{
Console.WriteLine("Unknown encountered on server. Message:'{0}' when writing an object", e.Message);
}
}
}

The above C# code snippet shows an insecure encryption algorithm vulnerability. It demonstrates an example of an AWS S3 client that is used to encrypt an object and upload it to an S3 bucket.

In this example, the PutObjectRequest object is used to specify the details of the object to be uploaded. The BucketName and Key properties are used to specify the bucket and object key respectively. The ContentBody property is used to specify the content of the object.

The critical part here is the ServerSideEncryptionMethod property. This is set to ServerSideEncryptionMethod.AES256, which is an insecure encryption algorithm.

AES256 is a symmetric encryption algorithm that is widely used but it is considered insecure because it uses a single key for both encryption and decryption. If this key is compromised, all data encrypted with it is at risk.

Moreover, the key management is handled by AWS, not the user. This means that the user has no control over the keys and cannot take full advantage of the AWS Key Management Service (KMS).

This is a security vulnerability because it exposes the user to potential data breaches. An attacker who gains access to the encryption key could decrypt all the data encrypted with it.

Steps

  • Replace the default encryption algorithm with a more secure encryption algorithm.
  • Use Customer Controlled Keys (CMK) instead of the default keys provided by the Key Management Service (KMS).
  • Configure the Amazon S3 client to use the Customer Controlled Keys (CMK) for encryption.

Compliant code

using Amazon.S3;
using Amazon.S3.Model;
using System;
using System.Threading.Tasks;

public class S3Encryption
{
private static readonly string bucketName = "your-aws-bucket";
private static readonly string keyName = "your-object-key";
private static IAmazonS3 s3Client;
private static readonly string customerMasterKeyId = "your-cmk-id"; // Replace with your CMK ID
private static readonly string region = "your-region"; // Replace with your region

public static void Main()
{
s3Client = new AmazonS3Client(Amazon.RegionEndpoint.USWest2);
Console.WriteLine("Encrypting an object and uploading to bucket.\\n");
EncryptingAnObjectAsync().Wait();
}

static async Task EncryptingAnObjectAsync()
{
try
{
var putRequest = new PutObjectRequest
{
BucketName = bucketName,
Key = keyName,
ContentBody = "This is the body of the S3 object.",
ServerSideEncryptionMethod = ServerSideEncryptionMethod.AWSKMS,
ServerSideEncryptionKeyManagementServiceKeyId = customerMasterKeyId
};

await s3Client.PutObjectAsync(putRequest);
}
catch (AmazonS3Exception e)
{
Console.WriteLine("Error encountered on server. Message:'{0}' when writing an object", e.Message);
}
catch (Exception e)
{
Console.WriteLine("Unknown encountered on server. Message:'{0}' when writing an object", e.Message);
}
}
}

The above code is a secure version of the previous code. The main changes are:

  1. The ServerSideEncryptionMethod is changed from AES256 to AWSKMS. This change is made to use the AWS Key Management Service (KMS) for encryption instead of the default AES256 encryption.

  2. A new field ServerSideEncryptionKeyManagementServiceKeyId is added to the PutObjectRequest. This field is set to the ID of the Customer Master Key (CMK) that you control. This ensures that the encryption uses your CMK and not the default keys provided by AWS.

  3. The customerMasterKeyId and region are added as static readonly fields. Replace "your-cmk-id" and "your-region" with your actual CMK ID and region.

By making these changes, you are taking full advantage of the AWS KMS service and ensuring that your data is encrypted using a key that you control. This is a best practice for securing your data in AWS.

References