Security group restricts SSH access from the internet
Alibaba Cloud ECS security groups provide stateful filtering of ingress and egress network traffic to cloud resources. This check verifies that no security group allows unrestricted ingress access to port 22 (SSH) from the internet (0.0.0.0/0 or ::/0). Restricting SSH access to trusted IP addresses significantly reduces the attack surface of ECS instances.
Risk
Unrestricted SSH access from the internet (0.0.0.0/0) exposes systems to brute force attacks, credential stuffing, and exploitation of SSH vulnerabilities. This can lead to unauthorized access, data exfiltration, and full system compromise, impacting confidentiality, integrity, and availability.
Run this check with Prowler
Run in Prowler Cloudprowler alibabacloud --checks ecs_securitygroup_restrict_ssh_internetRecommendation
Restrict SSH (port 22) access in security groups to only trusted IP addresses or CIDR blocks. Remove any rules allowing access from 0.0.0.0/0 or ::/0.
Remediation
CLI
aliyun ecs RevokeSecurityGroup --SecurityGroupId <security_group_id> --IpProtocol tcp --PortRange 22/22 --SourceCidrIp 0.0.0.0/0Terraform
resource "alicloud_security_group_rule" "deny_ssh_internet" {
type = "ingress"
ip_protocol = "tcp"
port_range = "22/22"
security_group_id = alicloud_security_group.example.id
cidr_ip = "10.0.0.0/8" # Restrict to internal network
policy = "accept"
}Other
Check Code
from prowler.lib.check.models import Check, CheckReportAlibabaCloud
from prowler.providers.alibabacloud.services.ecs.ecs_client import ecs_client
from prowler.providers.alibabacloud.services.ecs.lib.security_groups import (
is_public_cidr,
port_in_range,
)
class ecs_securitygroup_restrict_ssh_internet(Check):
"""Check if security groups restrict SSH (port 22) access from the internet."""
def execute(self) -> list[CheckReportAlibabaCloud]:
findings = []
check_port = 22 # SSH port
for sg_arn, security_group in ecs_client.security_groups.items():
report = CheckReportAlibabaCloud(
metadata=self.metadata(), resource=security_group
)
report.region = security_group.region
report.resource_id = security_group.id
report.resource_arn = security_group.arn
# Check ingress rules for unrestricted access to SSH port
has_unrestricted_access = False
for ingress_rule in security_group.ingress_rules:
# Check if rule allows traffic (policy == "accept")
if str(ingress_rule.get("policy", "accept")).lower() != "accept":
continue
# Check protocol (tcp for SSH)
protocol = ingress_rule.get("ip_protocol", "").lower()
if protocol not in ["tcp", "all"]:
continue
# Check if source is public (0.0.0.0/0)
source_cidr = ingress_rule.get("source_cidr_ip", "")
if not is_public_cidr(source_cidr):
continue
# Check if port range includes SSH port
port_range = ingress_rule.get("port_range", "")
if protocol == "all":
# If protocol is "all", all ports are open
has_unrestricted_access = True
break
elif port_in_range(port_range, check_port):
has_unrestricted_access = True
break
if has_unrestricted_access:
report.status = "FAIL"
report.status_extended = (
f"Security group {security_group.name} ({security_group.id}) "
f"has SSH port 22 open to the internet (0.0.0.0/0)."
)
else:
report.status = "PASS"
report.status_extended = (
f"Security group {security_group.name} ({security_group.id}) "
f"does not have SSH port 22 open to the internet."
)
findings.append(report)
return findings