MEDIUM CloudWatch · CIS 4.11

NACL changes alarm

Check ID: aws-cw-011

AWS-CW-011 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 Network ACL changes (CreateNetworkAcl, DeleteNetworkAcl, ReplaceNetworkAclEntry). Without this monitoring, subnet-level network changes go undetected.

Why it matters

Network ACLs are stateless firewalls at the subnet level that act as a second layer of defense beyond security groups. Unlike security groups, NACLs have explicit deny rules and apply to all resources in a subnet. Unauthorized NACL changes can bypass security group restrictions or block legitimate traffic, causing outages. In defense-in-depth architectures, NACLs are often the last barrier preventing lateral movement between subnets. NACL changes should be rare in production environments and are often a sign of either network troubleshooting gone wrong or an attacker attempting to open network paths between isolated segments.

Common causes

NACLs are less frequently modified than security groups, so monitoring for their changes is often overlooked. Teams troubleshooting connectivity issues may temporarily modify NACL rules and forget to revert them. The stateless nature of NACLs (requiring separate inbound and outbound rules) leads to trial-and-error changes that can accidentally open unintended access paths.

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.11 \
  --filter-pattern '{ ($.eventName = CreateNetworkAcl) || ($.eventName = CreateNetworkAclEntry) || ($.eventName = DeleteNetworkAcl) || ($.eventName = DeleteNetworkAclEntry) || ($.eventName = ReplaceNetworkAclEntry) || ($.eventName = ReplaceNetworkAclAssociation) }' \
  --metric-transformations metricName=CIS-4-11,metricNamespace=CISBenchmark,metricValue=1
# Create alarm:
aws cloudwatch put-metric-alarm \
  --alarm-name CIS-4.11 \
  --metric-name CIS-4-11 \
  --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_11" {
  name           = "CIS-4.11"
  log_group_name = aws_cloudwatch_log_group.cloudtrail.name
  pattern        = "{ ($.eventName = CreateNetworkAcl) || ($.eventName = CreateNetworkAclEntry) || ($.eventName = DeleteNetworkAcl) || ($.eventName = DeleteNetworkAclEntry) || ($.eventName = ReplaceNetworkAclEntry) || ($.eventName = ReplaceNetworkAclAssociation) }"

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

resource "aws_cloudwatch_metric_alarm" "cis_4_11" {
  alarm_name          = "CIS-4.11"
  metric_name         = "CIS-4-11"
  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.11 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