WAF-SEC-050 – Network Segmentation & Security Group Hardening
Beschreibung
All compute resources MUST be placed in private subnets unless they explicitly serve public traffic. Security groups MUST NOT allow unrestricted ingress from 0.0.0.0/0 or ::/0 on administrative ports (SSH port 22, RDP port 3389). Egress MUST be restricted to required destinations; unrestricted egress (0.0.0.0/0 on all ports) is prohibited for workloads handling sensitive data. Network ACLs (NACLs) and security groups MUST be used in combination for defense-in-depth. VPC resources MUST be logically segmented by workload tier (public, private, data).
Begründung
| Risiko | Beschreibung |
|---|---|
Risk |
Internet-facing resources or open management ports become direct attack vectors. |
Risk |
Lateral movement is easier when network segmentation and access rules are missing. |
Anforderungen
-
All compute resources MUST be placed in private subnets unless they explicitly serve public traffic.
-
Security groups MUST NOT allow unrestricted ingress from 0.0.0.0/0 or ::/0 on administrative ports (SSH port 22, RDP port 3389).
-
Egress MUST be restricted to required destinations; unrestricted egress (0.0.0.0/0 on all ports) is prohibited for workloads handling sensitive data.
-
Network ACLs (NACLs) and security groups MUST be used in combination for defense-in-depth.
-
VPC resources MUST be logically segmented by workload tier (public, private, data).
Implementierungsleitfaden
-
Implement the required configuration as code in Terraform or equivalent IaC.
-
Add an automated check to CI/CD so deviations are caught before deployment.
Reifegrade
| Level | Name | Kriterien |
|---|---|---|
L1 |
Ad hoc – control not consistently applied |
* Manual evidence exists for some workloads, but coverage is unknown. |
L2 |
Standardised – policy defined and communicated |
* A version-controlled policy, ADR, or standard describes the requirement. |
L3 |
Integrated – automated validation in CI/CD |
* Terraform checks run automatically on pull requests and report results. |
L4 |
Auditable – metrics and exceptions tracked |
* Control coverage, failures, and approved exceptions are reported quarterly. |
L5 |
Optimised – continuous improvement based on data |
* Control effectiveness is measured and iteratively improved. |
Checks
waf-sec-050.tf.aws.no-public-ip-internal-compute
Engine: terraform | Provider: aws | Automated: Ja
Internal compute resources must not be assigned public IP addresses
EC2 instances and launch templates used for application or internal workloads must have associate_public_ip_address = false to ensure they are not directly reachable from the internet.
Scope: resource — aws_instance, aws_launch_template
Assertions:
* associate_public_ip_address is false — Internal compute resources MUST NOT have public IP addresses assigned. Use private subnets and NAT Gateway for outbound access.
Remediation: Set associate_public_ip_address = false on all aws_instance and aws_launch_template resources used for internal workloads. Place these instances in private subnets. Use a NAT Gateway for outbound internet access and an Application Load Balancer in a public subnet for inbound traffic if required.
resource "aws_instance" "app" {
ami = data.aws_ami.ubuntu.id
instance_type = "t3.medium"
subnet_id = aws_subnet.private.id
associate_public_ip_address = false
vpc_security_group_ids = [aws_security_group.app.id]
tags = { Name = "app-server" }
}
resource "aws_instance" "app" {
ami = data.aws_ami.ubuntu.id
instance_type = "t3.medium"
subnet_id = aws_subnet.public.id
associate_public_ip_address = true # WAF-SEC-050 violation
vpc_security_group_ids = [aws_security_group.app.id]
}
waf-sec-050.tf.aws.no-unrestricted-ssh
Engine: terraform | Provider: aws | Automated: Ja
Security groups must not allow unrestricted SSH or RDP ingress from the internet
Security group ingress rules must not allow port 22 (SSH) or port 3389 (RDP) from 0.0.0.0/0 (IPv4) or ::/0 (IPv6). Administrative access must be provided via AWS Systems Manager Session Manager or a bastion host with restricted CIDR access.
Scope: resource — aws_security_group, aws_vpc_security_group_ingress_rule
Assertions:
* ingress json not contains pattern pattern "cidr_blocks":\\s*\\["0\\.0\\.0\\.0/0"\\] — Security group must not allow ingress from 0.0.0.0/0 on administrative ports. Restrict to known CIDR ranges or use SSM Session Manager.
Remediation: Remove any ingress rule allowing port 22 or 3389 from 0.0.0.0/0. For SSH access, use AWS Systems Manager Session Manager (requires SSM agent and IAM role with AmazonSSMManagedInstanceCore policy). For legacy SSH requirements, restrict the source CIDR to your organization’s VPN or office IP range.
resource "aws_security_group" "app" {
name = "app-server-sg"
vpc_id = aws_vpc.main.id
# No SSH ingress rule – use SSM Session Manager instead
egress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
description = "HTTPS outbound for AWS API calls"
}
}
resource "aws_security_group" "bad" {
name = "app-server-sg"
vpc_id = aws_vpc.main.id
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"] # WAF-SEC-050 violation: open SSH to internet
}
}
waf-sec-050.tf.azurerm.nic-no-public-ip
Engine: terraform | Provider: azurerm | Automated: Ja
Azure network interfaces for internal workloads must not have a public IP address
All azurerm_network_interface resources used for internal application workloads must leave ip_configuration.public_ip_address_id empty or unset.
Scope: resource — azurerm_network_interface
Assertions:
* ip_configuration.public_ip_address_id equals `` — Network interface for internal workloads must not have a public IP address assigned.
Remediation: Remove public_ip_address_id from the ip_configuration block of internal azurerm_network_interface resources. Place VMs behind an Azure Load Balancer or Application Gateway for inbound traffic if required.
resource "azurerm_network_interface" "app" {
name = "app-nic"
location = azurerm_resource_group.main.location
resource_group_name = azurerm_resource_group.main.name
ip_configuration {
name = "internal"
subnet_id = azurerm_subnet.private.id
private_ip_address_allocation = "Dynamic"
}
}
resource "azurerm_network_interface" "app" {
name = "app-nic"
location = azurerm_resource_group.main.location
resource_group_name = azurerm_resource_group.main.name
ip_configuration {
name = "internal"
subnet_id = azurerm_subnet.private.id
private_ip_address_allocation = "Dynamic"
public_ip_address_id = azurerm_public_ip.app.id
}
}
waf-sec-050.tf.azurerm.nsg-no-admin-internet
Engine: terraform | Provider: azurerm | Automated: Ja
Azure network security groups must not allow unrestricted SSH or RDP from the internet
All azurerm_network_security_group resources must not contain a security_rule that allows destination port 22 or 3389 from source_address_prefix "*" or "Internet".
Scope: resource — azurerm_network_security_group, azurerm_network_security_rule
Assertions:
* security_rule json not contains pattern pattern "destination_port_range":\s*"22" — NSG must not allow unrestricted SSH (port 22) from the internet.
* security_rule json not contains pattern pattern "destination_port_range":\s*"3389" — NSG must not allow unrestricted RDP (port 3389) from the internet.
Remediation: Remove or restrict administrative ingress rules in azurerm_network_security_group and azurerm_network_security_rule resources. Source CIDRs should be limited to known ranges; prefer Azure Bastion or JIT access.
resource "azurerm_network_security_group" "app" {
name = "app-nsg"
location = azurerm_resource_group.main.location
resource_group_name = azurerm_resource_group.main.name
# No SSH/RDP ingress from the internet
}
resource "azurerm_network_security_group" "bad" {
name = "bad-nsg"
location = azurerm_resource_group.main.location
resource_group_name = azurerm_resource_group.main.name
security_rule {
name = "AllowSSH"
priority = 100
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "22"
source_address_prefix = "Internet"
destination_address_prefix = "*"
}
}
waf-sec-050.tf.google.vm-no-access-config
Engine: terraform | Provider: google | Automated: Ja
Google Compute Engine instances for internal workloads must not have external IPs
All google_compute_instance resources used for internal application workloads must not contain a network_interface.access_config block (no external IP).
Scope: resource — google_compute_instance
Assertions:
* network_interface.access_config equals `` — Internal compute instances must not have an access_config block assigning an external IP.
Remediation: Remove the access_config block from network_interface on internal google_compute_instance resources. Use Cloud NAT for outbound internet access and a load balancer for inbound traffic if required.
resource "google_compute_instance" "app" {
name = "app-vm"
machine_type = "e2-medium"
zone = "europe-west3-a"
network_interface {
subnetwork = google_compute_subnetwork.private.id
}
}
resource "google_compute_instance" "app" {
name = "app-vm"
machine_type = "e2-medium"
zone = "europe-west3-a"
network_interface {
subnetwork = google_compute_subnetwork.private.id
access_config {
# external IP assigned
}
}
}
waf-sec-050.tf.google.firewall-no-admin-internet
Engine: terraform | Provider: google | Automated: Ja
Google Cloud firewalls must not allow unrestricted SSH or RDP from the internet
All google_compute_firewall resources allowing ingress must not allow ports 22 or 3389 from source_ranges containing "0.0.0.0/0".
Scope: resource — google_compute_firewall
Assertions:
* allow json not contains pattern pattern "ports":\s*\[\s*"22" — Firewall must not allow unrestricted SSH (port 22) from the internet.
* allow json not contains pattern pattern "ports":\s*\[\s*"3389" — Firewall must not allow unrestricted RDP (port 3389) from the internet.
Remediation: Restrict source_ranges on google_compute_firewall rules for management ports to trusted CIDRs. Prefer Identity-Aware Proxy (IAP) for administrative access.
resource "google_compute_firewall" "internal" {
name = "allow-internal"
network = google_compute_network.main.id
allow {
protocol = "tcp"
ports = ["443"]
}
source_ranges = ["10.0.0.0/8"]
}
resource "google_compute_firewall" "bad" {
name = "allow-ssh-internet"
network = google_compute_network.main.id
allow {
protocol = "tcp"
ports = ["22"]
}
source_ranges = ["0.0.0.0/0"]
}
waf-sec-050.tf.stackit.network-no-public-ssh
Engine: terraform | Provider: stackit | Automated: Ja
STACKIT network resources must not expose administrative ports to the internet
stackit_network and stackit_security_group rules must not allow unrestricted ingress from 0.0.0.0/0 to administrative ports (SSH/RDP/3389) or database ports. Management access must be restricted to trusted sources.
Scope: resource — stackit_network, stackit_security_group
Assertions:
* name attribute exists — STACKIT network resources must be defined and reviewed for unrestricted administrative access.
Remediation: Restrict ingress rules in STACKIT security groups to specific source CIDRs or VPN ranges. Do not expose SSH/RDP/3389 to the public internet.
resource "stackit_network" "app" {
project_id = var.stackit_project_id
name = "app-network"
}
# Ingress restricted to trusted office/VPN CIDR via STACKIT console or API
resource "stackit_network" "app" {
project_id = var.stackit_project_id
name = "app-network"
# Security group allows 0.0.0.0/0:22 – WAF-SEC-050 violation
}
waf-sec-050.tf.ovh.vps-no-public-admin
Engine: terraform | Provider: ovh | Automated: Ja
OVHcloud instances must not expose administrative ports to the internet
OVHcloud instances (ovh_cloud_project_instance, ovh_vps, ovh_dedicated_server) must not be reachable from 0.0.0.0/0 on administrative ports. Access must be restricted using OVHcloud firewall or customer-managed network ACLs.
Scope: resource — ovh_cloud_project_instance, ovh_vps, ovh_dedicated_server
Assertions:
* name attribute exists — OVHcloud instance must be defined and reviewed for unrestricted administrative access.
Remediation: Configure OVHcloud firewall rules or host-based firewalls to restrict SSH/RDP/WinRM to trusted sources. Document allowed source ranges.
resource "ovh_cloud_project_instance" "app" {
project_id = var.ovh_project_id
name = "app-vm"
flavor = "b2-7"
image = "Ubuntu 22.04"
# OVHcloud firewall restricts SSH to trusted CIDR
}
resource "ovh_cloud_project_instance" "app" {
project_id = var.ovh_project_id
name = "app-vm"
# SSH open to 0.0.0.0/0 – WAF-SEC-050 violation
}
waf-sec-050.tf.hcloud.firewall-no-public-admin
Engine: terraform | Provider: hcloud | Automated: Ja
Hetzner Cloud firewalls must block public administrative access
hcloud_firewall rules must not allow 0.0.0.0/0 ingress on administrative ports (SSH/RDP/3389). Management access must be limited to trusted source IPs or a bastion network.
Scope: resource — hcloud_firewall
Assertions:
* rule json not contains pattern pattern "source_ips":\s*\[\s*"0\\.0\\.0\\.0/0"\s*\] — Hetzner Cloud firewall must not allow 0.0.0.0/0 on administrative ports.
Remediation: Create hcloud_firewall rules that restrict SSH and other admin ports to trusted source IPs. Attach the firewall to all production servers.
resource "hcloud_firewall" "app" {
name = "app-firewall"
rule {
direction = "in"
protocol = "tcp"
port = "22"
source_ips = ["203.0.113.0/24"]
}
}
resource "hcloud_firewall" "app" {
name = "app-firewall"
rule {
direction = "in"
protocol = "tcp"
port = "22"
source_ips = ["0.0.0.0/0"] # WAF-SEC-050 violation
}
}
Evidenz
| Art | Erforderlich | Beschreibung |
|---|---|---|
|
Erforderlich |
Terraform configuration implementing the control. |
|
Erforderlich |
Policy, ADR, or standard documenting the requirement. |
|
Optional |
Cloud console or API output confirming runtime state. |
Verwandte Controls
-
WAF-SEC-130 == Regulatorisches Mapping
| Framework | Controls |
|---|---|
ISO 27001:2022 |
* A.8.20 – Networks security * A.8.21 – Security of network services * A.8.22 – Segregation of networks |
ISO 27017 |
* CLD.13.1 – Network security management |
CIS Controls v8 |
* CIS 4 – Secure Configuration of Enterprise Assets * CIS 12 – Network Infrastructure Management * CIS 13 – Network Monitoring and Defense |
CSA STAR |
* CCM IVS-03 – Network Security * CCM IVS-09 – Segmentation and Segregation |
PCI DSS v4.0 |
* Req 1 – Install and maintain network security controls * Req 1.2 – Network segmentation |
SOC 2 Type II |
* CC6.6 – Network access boundaries |
GDPR |
* Art. 32 – Security of processing |
NIS2 |
* Art. 21(2)(c) – Network and information system security |
DORA |
* Art. 9 – Protection and prevention |
EUCS (ENISA) |
* CSC-01 – Network security controls * CSC-04 – Network segmentation |
BSI C5:2020 |
* COM-01 – Network architecture and segmentation * COM-02 – Network access controls |
IT-Grundschutz |
* NET.1.1 – Netzarchitektur und -design * NET.3.2 – Firewall |
TISAX |
* Information security – Network segmentation |
ANSSI SecNumCloud |
* Domain – Network security and segmentation |
BIO |
* BIO – Netwerksegmentatie |
ENS High |
* mp.com.1 – Perímetro seguro * mp.com.4 – Segregación de redes |
UK Cyber Essentials |
* CE.FW – Firewalls |
UK NCSC CAF |
* B4 – System security – network and protective monitoring |
UK GDPR |
* Art. 32 – Security of processing |
NIST SP 800-53 |
* SC-7 – Boundary Protection * AC-4 – Information Flow Enforcement |
NIST CSF 2.0 |
* PR.IR-01 – Networks are protected from unauthorized access |
FedRAMP |
* SC-7, AC-4 (Moderate/High baseline) |
CMMC 2.0 |
* SC.L2-3.13.1 – Monitor, control and protect communications * SC.L2-3.13.5 – Implement subnetworks for publicly accessible components |
ASD Essential 8 |
* E8.4 – User application hardening (browser/network) |
IRAP |
* ISM – Network security |
CCCS PBMM |
* SC-7 – Boundary protection |
MAS TRM |
* Ch.9 – IT resilience – Network security |
ISMAP |
* Network access controls and segmentation |
FISC |
* Technical measures – Network access control |