Skip to main content

Insecure encryption algorithm - Default encryption

Need

Secure encryption algorithm - Utilize Customer Controlled Keys (CMK)

Context

  • Usage of Scala 2.11 for writing and running Scala code
  • Usage of AWS Java SDK S3 for interacting with Amazon S3 storage service

Description

Non compliant code

import com.amazonaws.services.s3.AmazonS3ClientBuilder
import com.amazonaws.services.s3.model.ObjectMetadata
import com.amazonaws.services.s3.model.PutObjectRequest

val s3client = AmazonS3ClientBuilder.defaultClient()

val objectMetadata = new ObjectMetadata()
objectMetadata.setSSEAlgorithm(ObjectMetadata.AES_256_SERVER_SIDE_ENCRYPTION)

val putObjectRequest = new PutObjectRequest("bucketName", "key", new File("filePath"))
putObjectRequest.setMetadata(objectMetadata)

s3client.putObject(putObjectRequest)

The above code represents an example of using the AWS S3 client in a Play Framework application written in Scala. The code is written to upload a file to an S3 bucket with server-side encryption.

The vulnerability lies in the line where the Server-Side Encryption (SSE) algorithm is set. The code uses the AES_256_SERVER_SIDE_ENCRYPTION, which is a default encryption provided by AWS.

This is considered insecure because it does not fully utilize the AWS Key Management Service (KMS). The default encryption keys are managed by AWS and do not provide the same level of control and security as using Customer Managed Keys (CMK).

Using CMKs, you can create, own, and manage your cryptographic keys and control their use across all AWS services. This is important for organizations that have specific compliance requirements related to key management.

Therefore, the use of default encryption keys when more secure options are available is considered a vulnerability.

Steps

  • Use a customer-managed key (CMK) instead of the default encryption key provided by Amazon S3.
  • Create a CMK in the AWS Key Management Service (KMS) console.
  • Update the code to specify the CMK when setting the server-side encryption algorithm.
  • Replace the usage of 'AmazonS3ClientBuilder.defaultClient()' with a custom client configuration that includes the CMK.
  • Ensure that the CMK has appropriate permissions to access the S3 bucket.
  • Test the updated code to verify that the CMK is being used for encryption.

Compliant code

import com.amazonaws.services.s3.AmazonS3ClientBuilder
import com.amazonaws.services.s3.model.ObjectMetadata
import com.amazonaws.services.s3.model.PutObjectRequest
import com.amazonaws.services.s3.model.SSEAwsKeyManagementParams

// Create a KMS client
val kmsClient = AWSKMSClientBuilder.standard().build()

// Create a CMK
val createKeyRequest = new CreateKeyRequest()
val createKeyResult = kmsClient.createKey(createKeyRequest)
val cmkId = createKeyResult.getKeyMetadata().getKeyId()

// Create a custom S3 client configuration that includes the CMK
val s3client = AmazonS3ClientBuilder.standard()
.withRegion(Regions.DEFAULT_REGION)
.withCredentials(new AWSStaticCredentialsProvider(credentials))
.build()

val objectMetadata = new ObjectMetadata()
objectMetadata.setSSEAlgorithm(ObjectMetadata.AES_256_SERVER_SIDE_ENCRYPTION)

val putObjectRequest = new PutObjectRequest("bucketName", "key", new File("filePath"))
putObjectRequest.setMetadata(objectMetadata)

// Specify the CMK when setting the server-side encryption algorithm
val sseAwsKeyManagementParams = new SSEAwsKeyManagementParams(cmkId)
putObjectRequest.setSSEAwsKeyManagementParams(sseAwsKeyManagementParams)

s3client.putObject(putObjectRequest)

The updated code first creates a Key Management Service (KMS) client and then uses this client to create a Customer Managed Key (CMK). The CMK ID is then stored in the cmkId variable.

Next, a custom S3 client configuration is created that includes the CMK. This is done by using the AmazonS3ClientBuilder.standard() method instead of the AmazonS3ClientBuilder.defaultClient() method. The region and credentials are set in the custom configuration.

The ObjectMetadata and PutObjectRequest are created as before, but now the PutObjectRequest is updated to specify the CMK when setting the server-side encryption algorithm. This is done by creating a new SSEAwsKeyManagementParams object with the CMK ID and setting this object in the PutObjectRequest.

Finally, the putObject method of the S3 client is called with the updated PutObjectRequest. This ensures that the CMK is used for server-side encryption when the object is put in the S3 bucket.

References