The Security of DevSecOps - Terraform Code
This past October, I had the opportunity to speak with Robin Wood (@digininja) about “The Security of DevSecOps” at Wild West Hackin Fest in Deadwood, South Dakota. We felt that this was an intriguing topic to discuss since a large number of organizations are employing a form of DevOps within their company and we wanted to proactively have a discussion about how attackers could attack different DevOps technologies. Over the course of a series of blog posts, I'll cover two different pieces of DevOps (specifically Terraform and Jenkins) along with aspects of both technologies to be aware of.
Terraform is a technology that allows its users to build and deploy "infrastructure as code". What makes Terraform incredibly useful is the ability to "code" your infrastructure to be a certain size and configuration and Terraform will automate deploying the infrastructure by interacting with the APIs of various cloud hosting providers (AWS, Azure, Digital Ocean, etc.). Let's take a look at what some sample Terraform code can look like.
Resource Groups and Network Information
In the image above, you can discern multiple pieces of information. First, we know that this code is going to be deployed into Azure not only by variable names, but also the resource creation names (azurerm_public_ip, etc.). This creates a resource group within Azure called "private-net-group" within the West US datacenter. Additionally, we know that there is one large private network (10.0.0.0/8) and a smaller subnet which where the different resources will be deployed (10.12.10.0/24). Finally, the above code block is requesting a static IP address for a piece of infrastructure (defined in an image below).
While nothing from this block of code is inherently sensitive, an attack would now have information about the network ranges used by this developer/company.
The "azurerm_network_security_group" resource allows you to essentially create firewall rules and govern what can access the resources you deploy within your cloud environment. Based on the names used in the above code, it's reasonable to assume that these rules are for protecting a PFSense system within Azure.
Based on the above rules, only two ports are open and allowing incoming traffic from the Internet: TCP port 443 (HTTPS) is allowed and UDP port 1194 (OpenVPN) is also allowed. It's likely that these rules allow administrators to configure the PFSense device over HTTPS and also allow incoming OpenVPN connections for remote access into the Azure private subnet.
Similar to the "Resource Groups and Network Information" section above, the information contained in this block of code isn't devastating if it would become public. However, it is extra information an attacker would have that could be used to build targeted attacks against the cloud environment.
Individual IP Addressing
This section of code is responsible for building a network interface that can be "attached" to a cloud resource, such as a virtual machine. In this case, it's reasonable to assume that it is going to be a virtual interface for a Windows 10 system.
The biggest takeaway from this code block is learning that the network interface is going to have a static IP address - specifically "10.12.10.15". Nothing really damning here, but to continue the theme, this provides an attacker additional information about the cloud environment.
Finally, we're getting to the good stuff. The virtual machine configuration has the information that would truly present a problem if discovered by an attacker. Based on the information above, we have a couple different pieces of information that are useful to us:
- Operating system of the virtual machine - Windows 10
- The build of Windows 10 that's used - 17134
- Discovery that automative upgrades are set to false
- Computer hostname - TestWin10
- Local admin username - LocalAdminSystem
- Local admin password - TotallyNotAVirus!
Assuming this system is accessible over the network (either has a public IP address or we are connected in over a VPN connection), we have all the information that is necessary to attempt to compromise the workstation.
Are We Screwed?
In spite of everything that can be gathered, basic security practices that any sized company can implement will help protect your infrastructure, virtual or not. For starters, after deploying your virtual machines with Terraform, at a minimum change the local admin password. If it's an option, create a new administrative account and disable the "built-in" username and password coded within Terraform.
You should also restrict access to your Terraform codebase. Beyond the obvious of it containing a local admin account's credentials, an attacker could modify the code to contain rogue cloud resources, modify existing resources -your imagination is the limit.
I hope this helps give an initial overview of Terraform code and the security considerations you should keep in mind. If you have any questions at all, don't hesitate to contact us!