infrastructure-as-code
format
cloud
region
region IDs differ per CSP — AWS uses us-east-1, Azure uses eastus, GCP uses us-central1.
terraform {
required_providers {
aws = { source = "hashicorp/aws", version = "~> 5.0" }
random = { source = "hashicorp/random", version = "~> 3.6" }
}
}
provider "aws" {
region = "us-east-1"
}
resource "random_id" "suffix" {
byte_length = 4
}
data "aws_ami" "al2023" {
most_recent = true
owners = ["amazon"]
filter {
name = "name"
values = ["al2023-ami-*-x86_64"]
}
}
# Public SSH/RDP host
# vulnerabilities: NET-007, VM-014, LOG-002
resource "aws_security_group" "vm_public_ssh" {
name = "vbuild-vm-public-ssh"
description = "INTENTIONALLY VULNERABLE — open to the world"
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 3389
to_port = 3389
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
resource "aws_instance" "vm_public_ssh" {
ami = data.aws_ami.al2023.id
instance_type = "t3.micro"
vpc_security_group_ids = [aws_security_group.vm_public_ssh.id]
associate_public_ip_address = true
tags = { Name = "vbuild-vm-public-ssh" }
}
# Public object bucket
# vulnerabilities: S3-001, S3-004, S3-010
resource "aws_s3_bucket" "data_public_bucket" {
bucket = "vbuild-public-${random_id.suffix.hex}"
force_destroy = true
}
resource "aws_s3_bucket_ownership_controls" "data_public_bucket" {
bucket = aws_s3_bucket.data_public_bucket.id
rule {
object_ownership = "BucketOwnerPreferred"
}
}
resource "aws_s3_bucket_public_access_block" "data_public_bucket" {
bucket = aws_s3_bucket.data_public_bucket.id
block_public_acls = false
block_public_policy = false
ignore_public_acls = false
restrict_public_buckets = false
}
resource "aws_s3_bucket_acl" "data_public_bucket" {
depends_on = [
aws_s3_bucket_ownership_controls.data_public_bucket,
aws_s3_bucket_public_access_block.data_public_bucket,
]
bucket = aws_s3_bucket.data_public_bucket.id
acl = "public-read-write"
}
intentionally vulnerable. Apply only in an isolated sub-account / project, time-boxed and tagged. Never deploy on top of production.