VPC Flow Logs Inbound Port Allowlist


Description

VPC Flow Logs observed inbound traffic violating the port allowlist.

Query · python

from ipaddress import ip_network

from panther_aws_helpers import aws_rule_context

APPROVED_PORTS = {
    80,
    443,
}


def rule(event):
    # Can't perform this check without a destination port
    if not event.udm("destination_port"):
        return False

    # Only monitor for non allowlisted ports
    if event.udm("destination_port") in APPROVED_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)

Analyst notes

Block the unapproved traffic, or update the approved ports list.

Raw source VPC Flow Logs Inbound Port Allowlist · Panther Python
Esc
Published by panther-labs/panther-analysis ↗, licensed under Apache 2.0 ↗. Reproduced here unmodified.
AnalysisType: rule
Filename: aws_vpc_inbound_traffic_port_allowlist.py
RuleID: "AWS.VPC.InboundPortWhitelist"
DisplayName: "VPC Flow Logs Inbound Port Allowlist"
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 allowlist.
Runbook: >
  Block the unapproved traffic, or update the approved 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_allowlist.py ------

from ipaddress import ip_network

from panther_aws_helpers import aws_rule_context

APPROVED_PORTS = {
    80,
    443,
}


def rule(event):
    # Can't perform this check without a destination port
    if not event.udm("destination_port"):
        return False

    # Only monitor for non allowlisted ports
    if event.udm("destination_port") in APPROVED_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)

Detection rules belong to the projects that publish them and remain under their own licenses. This site indexes and links to them; it claims no rights in them.