MEDIUM CloudWatch · CIS 4.13

Route table changes alarm

Check ID: aws-cw-013

AWS-CW-013 is an AWS security check performed by cloud-audit, an open-source AWS security scanner. Checks if a CloudWatch metric filter and alarm exist to detect route table changes (CreateRoute, DeleteRoute, ReplaceRoute, CreateRouteTable). Without this monitoring, traffic routing changes go undetected.

Why it matters

Route table changes control where network traffic flows within your VPC and to external destinations. An attacker can redirect traffic through a compromised EC2 instance by adding a route that intercepts traffic destined for other subnets, enabling man-in-the-middle attacks. Deleting the default route to a NAT gateway can silently break outbound connectivity for private subnets, causing application failures that are difficult to diagnose. Route changes can also be used to exfiltrate data by routing traffic through an attacker-controlled VPN or transit gateway connection. In multi-account architectures using Transit Gateway, a single route change can affect traffic flow across the entire organization.

Common causes

Route table changes occur during normal infrastructure operations like adding new subnets or VPC peering connections, making it easy to dismiss alerts as expected activity. Terraform apply operations that modify networking resources generate route changes that may not be reviewed by the security team. Teams troubleshooting connectivity issues may add temporary routes directly in the console and forget to remove them.

Detection

Run cloud-audit to detect this issue:

pip install cloud-audit
cloud-audit scan -R

The -R flag includes remediation details for every finding, including this one.

Remediation: AWS CLI

# Create metric filter:
aws logs put-metric-filter \
  --log-group-name <CLOUDTRAIL_LOG_GROUP> \
  --filter-name CIS-4.13 \
  --filter-pattern '{ ($.eventName = CreateRoute) || ($.eventName = CreateRouteTable) || ($.eventName = ReplaceRoute) || ($.eventName = ReplaceRouteTableAssociation) || ($.eventName = DeleteRouteTable) || ($.eventName = DeleteRoute) || ($.eventName = DisassociateRouteTable) }' \
  --metric-transformations metricName=CIS-4-13,metricNamespace=CISBenchmark,metricValue=1
# Create alarm:
aws cloudwatch put-metric-alarm \
  --alarm-name CIS-4.13 \
  --metric-name CIS-4-13 \
  --namespace CISBenchmark \
  --statistic Sum --period 300 --threshold 1 \
  --comparison-operator GreaterThanOrEqualToThreshold \
  --evaluation-periods 1 \
  --alarm-actions <SNS_TOPIC_ARN>

Remediation: Terraform

resource "aws_cloudwatch_log_metric_filter" "cis_4_13" {
  name           = "CIS-4.13"
  log_group_name = aws_cloudwatch_log_group.cloudtrail.name
  pattern        = "{ ($.eventName = CreateRoute) || ($.eventName = CreateRouteTable) || ($.eventName = ReplaceRoute) || ($.eventName = ReplaceRouteTableAssociation) || ($.eventName = DeleteRouteTable) || ($.eventName = DeleteRoute) || ($.eventName = DisassociateRouteTable) }"

  metric_transformation {
    name      = "CIS-4-13"
    namespace = "CISBenchmark"
    value     = "1"
  }
}

resource "aws_cloudwatch_metric_alarm" "cis_4_13" {
  alarm_name          = "CIS-4.13"
  metric_name         = "CIS-4-13"
  namespace           = "CISBenchmark"
  statistic           = "Sum"
  period              = 300
  threshold           = 1
  comparison_operator = "GreaterThanOrEqualToThreshold"
  evaluation_periods  = 1
  alarm_actions       = [aws_sns_topic.alerts.arn]
}

Compliance mapping

This check maps to CIS 4.13 in the CIS AWS Foundations Benchmark. The CIS Benchmark provides prescriptive guidance for configuring security options for a subset of AWS services.

This check is part of cloud-audit - install with pip install cloud-audit