AnalysisType: rule
Filename: aws_vpc_inbound_traffic_port_blocklist.py
RuleID: "AWS.VPC.InboundPortBlacklist"
DisplayName: "VPC Flow Logs Inbound Port Blocklist"
Enabled: false
LogTypes:
- AWS.VPCFlow
- OCSF.NetworkActivity
Tags:
- AWS
- DataModel
- Configuration Required
- Security Control
- Command and Control:Non-Standard Port
Reports:
MITRE ATT&CK:
- TA0011:T1571
Reference: https://docs.aws.amazon.com/vpc/latest/userguide/flow-logs.html
Severity: High
Description: >
VPC Flow Logs observed inbound traffic violating the port blocklist.
Runbook: >
Block the unapproved traffic, or update the unapproved ports list.
SummaryAttributes:
- srcaddr
- dstaddr
- dstport
Tests:
- Name: Public to Private IP on Restricted Port
ExpectedResult: true
Log:
{
"dstPort": 22,
"dstAddr": "10.0.0.1",
"srcAddr": "1.1.1.1",
"p_log_type": "AWS.VPCFlow",
}
- Name: Public to Private IP on Allowed Port
ExpectedResult: false
Log:
{
"dstPort": 443,
"dstAddr": "10.0.0.1",
"srcAddr": "1.1.1.1",
"p_log_type": "AWS.VPCFlow",
}
- Name: Private to Private IP on Restricted Port
ExpectedResult: false
Log:
{
"dstPort": 22,
"dstAddr": "10.0.0.1",
"srcAddr": "10.10.10.1",
"p_log_type": "AWS.VPCFlow",
}
- Name: Public to Private IP on Restricted Port - OCSF
ExpectedResult: true
Log:
{
"dst_endpoint": { "ip": "10.0.0.1", "port": 22 },
"src_endpoint": { "ip": "1.1.1.1" },
"p_log_type": "OCSF.NetworkActivity",
}
- Name: Public to Private IP on Allowed Port - OCSF
ExpectedResult: false
Log:
{
"dst_endpoint": { "ip": "10.0.0.1", "port": 443 },
"src_endpoint": { "ip": "1.1.1.1" },
"p_log_type": "OCSF.NetworkActivity",
}
# ------ paired body: aws_vpc_inbound_traffic_port_blocklist.py ------
from ipaddress import ip_network
from panther_aws_helpers import aws_rule_context
CONTROLLED_PORTS = {
22,
3389,
}
def rule(event):
# Only monitor for blocklisted ports
#
# Defaults to True (no alert) if 'dstport' is not present
if event.udm("destination_port") not in CONTROLLED_PORTS:
return False
# Only monitor for traffic coming from non-private IP space
#
# Defaults to True (no alert) if 'srcaddr' key is not present
source_ip = event.udm("source_ip") or "0.0.0.0/32"
if not ip_network(source_ip).is_global:
return False
# Alert if the traffic is destined for internal IP addresses
#
# Defaults to False(no alert) if 'dstaddr' key is not present
destination_ip = event.udm("destination_ip") or "1.0.0.0/32"
return not ip_network(destination_ip).is_global
def alert_context(event):
return aws_rule_context(event)