Public Resource Exposure
Public Resource Exposure
Public resource exposure remains the most common and damaging IaC vulnerability. Cloud providers design services to be secure by default, but IaC configurations can inadvertently override these defaults. S3 buckets made public through misconfigured ACLs or policies have led to countless data breaches. Databases exposed to the internet through security group misconfigurations provide attackers with direct access to sensitive data.
The complexity of cloud networking contributes to public exposure vulnerabilities. Developers might not fully understand the implications of CIDR blocks like 0.0.0.0/0 or the interaction between network ACLs and security groups. IaC templates copied from tutorials or examples often contain permissive network configurations suitable for learning but dangerous in production.
# Common PUBLIC EXPOSURE vulnerabilities in Terraform
# VULNERABLE: S3 bucket with public read access
resource "aws_s3_bucket" "vulnerable_bucket" {
bucket = "my-app-data"
acl = "public-read" # DANGER: Anyone can read bucket contents
}
# VULNERABLE: S3 bucket with public access through bucket policy
resource "aws_s3_bucket_policy" "vulnerable_policy" {
bucket = aws_s3_bucket.data.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Sid = "PublicReadGetObject"
Effect = "Allow"
Principal = "*" # DANGER: Allows anyone
Action = "s3:GetObject"
Resource = "${aws_s3_bucket.data.arn}/*"
}
]
})
}
# SECURE: S3 bucket with proper access controls
resource "aws_s3_bucket" "secure_bucket" {
bucket = "my-app-data"
}
resource "aws_s3_bucket_public_access_block" "secure_bucket_pab" {
bucket = aws_s3_bucket.secure_bucket.id
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
resource "aws_s3_bucket_acl" "secure_bucket_acl" {
bucket = aws_s3_bucket.secure_bucket.id
acl = "private"
}
# VULNERABLE: RDS instance exposed to internet
resource "aws_db_instance" "vulnerable_database" {
identifier = "myapp-database"
engine = "postgres"
instance_class = "db.t3.micro"
username = "admin"
password = "changeme123" # Additional vulnerability: hardcoded password
publicly_accessible = true # DANGER: Database accessible from internet
vpc_security_group_ids = [aws_security_group.vulnerable_db_sg.id]
}
# VULNERABLE: Security group allowing all inbound traffic
resource "aws_security_group" "vulnerable_db_sg" {
name = "database-sg"
ingress {
from_port = 5432
to_port = 5432
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"] # DANGER: Allows connections from anywhere
}
}
# SECURE: RDS instance with proper network isolation
resource "aws_db_instance" "secure_database" {
identifier = "myapp-database"
engine = "postgres"
instance_class = "db.t3.micro"
username = "admin"
password = random_password.db_password.result
publicly_accessible = false # Not accessible from internet
db_subnet_group_name = aws_db_subnet_group.private.name
vpc_security_group_ids = [aws_security_group.secure_db_sg.id]
storage_encrypted = true # Additional security: encryption at rest
backup_retention_period = 7
backup_window = "03:00-04:00"
}
# SECURE: Security group with restricted access
resource "aws_security_group" "secure_db_sg" {
name = "database-sg"
vpc_id = aws_vpc.main.id
ingress {
from_port = 5432
to_port = 5432
protocol = "tcp"
security_groups = [aws_security_group.app_sg.id] # Only from app servers
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["127.0.0.1/32"] # No outbound connections
}
}
Load balancers and API gateways present similar exposure risks. While these resources legitimately need internet access, misconfigurations can expose backend services unintentionally. Missing authentication requirements, overly permissive CORS policies, or incorrect target group configurations create attack vectors.