Yesterday I stumbled upon an update to a Terraform module that addressed this issue.
The module itself is for launching NAT instances on AWS, giving resources in private subnets the ability to access the public internet. In short, the module creates a nat_ha_role
with an overly permissive policy:
Within the "Principal": {"AWS": "*"}
section, "AWS": "*"
means that any AWS account or service can assume this role. Anybody who discovered the role’s ARN could assume that role, gaining the same permissions as the NAT instance. This role has the following policy actions attached:
"ec2:ReplaceRoute",
"ec2:CreateRoute",
"ec2:DeleteRoute",
"ec2:DescribeRouteTables",
"ec2:DescribeNetworkInterfaces",
"ec2:DescribeInstanceAttribute"
An attacker has tons of options here if they assume this role:
- Adding new routes to the VPC’s route table, possibly sending traffic to an external IP address they control
- Deleting routes, effectively causing DoS within the VPC
- Inspecting the detail of all route tables on the VPC, understanding network layout and identifying more routes to manipulate
- Identifying EC2 attributes such as instance type, kernel version (”which exploits should I use”), block device mappings & sizes, and user data to identify potentially sensitive data stored on attached volumes or in user scripts executed on boot
The problem with Terraform modules
The maintainer was responsive and patched the module once the issue was surfaced. Unfortunately, this isn’t an isolated incident. Publicly available Terraform modules may be rife with misconfigurations, from publicly available resources to overly permissive roles.
Using Terraform modules puts organizations at risk to deploying these misconfigurations into production. The benefit of modules is that they are templated Terraform - but that is also a drawback. Inexperienced Terraform and/or cloud users, people rushed for time, or even somebody who just wasn’t paying attention could easily miss an issue like this.
Even though this may have been a relatively old module (first created 9 years ago), the module itself doesn’t appear unmaintained and is possibly used by organizations with critical data and applications. One active, publicly available fork is by Indellient, a consulting shop recently acquired by Levio that helps companies deploy infrastructure.
Consider the number of Terraform modules (thousands) and their adoption by developers around the world. It is certain that misconfiguration like this exists in production environments around the world. Do yourself a favor and check IAM config in your Terraform modules to see if you’re using an overly permissive role.
Prevention with Resourcely
Even if an organization wanted to continue using Terraform modules, they could prevent this type of overly permissive roles with Resourcely Guardrails. Something similar to the below Guardrail would prevent an IAM role with the offending assume_role_policy
from making it into production, stopping a merge and sending the PR for approval (or adjustment) to the appropriate team.
You can get started with Resourcely Guardrails (with our without Terraform modules) here.