Skip to content

Prerequisites

  • projectx-prod-vpc has been created with subnets configured.
  • VPC Flow Logs have been enabled and are delivering logs to your S3 security datalake (see VPC Flow Logs & Integration).
  • Wazuh is configured to ingest VPC Flow Logs from S3 (see VPC Flow Logs & Integration).
  • project-x-sec-box configured with Wazuh.

Note

This guide builds on the Open VPC Configuration attack scenario. The detections below are designed to identify indicators of that attack in VPC Flow Log data.

Network Topology

Base Layout
(Click to zoom)

Overview

VPC Flow Logs capture network traffic (source/destination IPs, ports, protocols, and whether traffic was accepted or rejected). By creating Wazuh detection rules, you can identify patterns consistent with the Open VPC Configuration attack—such as inbound traffic from the internet to high-value ports (SSH, RDP, databases) and port-scanning behavior.

This guide provides custom Wazuh rules to deploy on your Wazuh manager.

Detection Strategy

How would we detect malicious activity?

Well, we have the visibility, through our logs.

We can start with the attack and work backward...

Attackers scan for open ports (discovery), probe high-value ports (enumeration), then attempt access (exploitation).

In VPC Flow Logs, we look for flows where source IP (attacker), destination port (target service), and action (ACCEPT/REJECT) tell the story.

Legitimate access typically comes from internal ranges (10.x, 172.16–31.x, 192.168.x).

Uncommon or unknown external IPs hitting SSH, RDP, or database ports is a strong signal. Especially if they continously attempt to establish a connection.

Port scanning shows as one source IP connecting to multiple high-value ports in a short window—we detect that by correlating alerts from the same source. The rules below encode these patterns.

So here's what we can come up with...

Attack Phase VPC Flow Log Indicator Detection Approach
Discovery / Scanning Same source IP connecting to multiple high-value ports in short time Port scan detection
Exploitation Inbound traffic from external IPs to SSH (22), RDP (3389), DB ports (3306, 5432, 1433) High-value port exposure
Exploitation Accepted (ACCEPT) traffic to database ports from non-private IPs Database port exposure

VPC Flow Log fields used in our rules include:

  • srcaddr / pkt-srcaddr: Source IP (attacker or scanner)
  • dstaddr / pkt-dstaddr: Destination IP (your instance)
  • dstport: Destination port (service being targeted)
  • action: ACCEPT or REJECT

Create Wazuh Detection Rules

High-Value Port Exposure (Open VPC)

We want to detect inbound traffic from the internet to high-risk ports. The open_vpc scenario exposes SSH (22), RDP (3389), and database ports (3306, 5432, 1433) to 0.0.0.0/0. Let's build the rule step by step.

Rule Description In Layman Terms

Our condition is: "Alert when we see ACCEPTed traffic to a high-value port (22, 3389, etc.) and the source IP is not in a private range." We express this with three requirements:

  1. The event must be a VPC Flow Log (we inherit that from the grouping rule).
  2. The destination port and action must match our criteria.
  3. The source IP must be external.

Wazuh Rule Syntax Walkthrough

Each rule is an XML <rule> element. Here's what each part does:

Element Purpose Example
level Alert severity (0–16). Higher = more severe. 10 = warning, 12 = critical. 10
field name="data.aws.dstport" Match the decoded field aws.dstport against a regex. 22 = port 22
field name="data.aws.action" Match the action field. ACCEPT = traffic was allowed
field name="data.aws.srcaddr Match the srcaddr field. srcaddr against a range of IPs
description Human-readable text for the alert. Shown in the dashboard

The External-IP Regex

We need to exclude private addresses: 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16.

Luckily, with the help of AI Models, generating the proper regex is no longer difficult.

The regex uses a negative lookahead (?!...) to skip those:

  • (?!10\.|172\.(1[6-9]|2[0-9]|3[0-1])\.|192\.168\.)"not starting with 10., 172.16–31., or 192.168."
  • [0-9]+\.[0-9]+\.[0-9]+\.[0-9]+ — then match a valid IPv4 address

So we're matching: "an IP that does not start with a private prefix."

Create a Monitor

If you can recall from Enterprise 101, we used the "Alerting" capability inside Wazuh. Under Alerting, we can create a Monitor, which will run a pre-defined query against all incoming logs. If the log matches the query content, an alert is generated.

We will use the Monitoring and Alerting capability to capture rogue opened ports.

The workflow for the following be as follow:

Navigate to AlertingMonitors.

Monitor Details:

  • Monitor name: Name your monitor. Select "Per query monitor".

  • Monitor type: Choose "Extraction query editor".

Click To Zoom
(Click to zoom)

Schedule:

  • By interval.

  • Run every 1 Minute(s).

Click To Zoom
(Click to zoom)

Select Data:

  • Indexes: wazuh-alerts-4.x-*
Click To Zoom
(Click to zoom)

Query: Paste in Query.

Click To Zoom
(Click to zoom)

Triggers:

  • Trigger Name: Name Trigger.

  • Severity level: Choose severity level.

Click To Zoom
(Click to zoom)

Inbound SSH Exposed To The Internet

<!-- CA101: Inbound traffic to PORT from source (open security group indicator) -->
{
    "size": 0,
    "query": {
        "bool": {
            "filter": [
                {
                    "term": {
                        "data.aws.action": {
                            "value": "ACCEPT",
                            "boost": 1
                        }
                    }
                },
                {
                    "term": {
                        "data.aws.dstport": {
                            "value": 22,
                            "boost": 1
                        }
                    }
                }
            ],
            "must_not": [
                {
                    "range": {
                        "data.aws.srcaddr": {
                            "from": "10.0.0.0",
                            "to": "10.255.255.255",
                            "include_lower": true,
                            "include_upper": true,
                            "boost": 1
                        }
                    }
                },
                {
                    "range": {
                        "data.aws.srcaddr": {
                            "from": "172.16.0.0",
                            "to": "172.31.255.255",
                            "include_lower": true,
                            "include_upper": true,
                            "boost": 1
                        }
                    }
                },
                {
                    "range": {
                        "data.aws.srcaddr": {
                            "from": "192.168.0.0",
                            "to": "192.168.255.255",
                            "include_lower": true,
                            "include_upper": true,
                            "boost": 1
                        }
                    }
                }
            ],
            "adjust_pure_negative": true,
            "boost": 1
        }
    }
}

Inbound RDP/VNC Exposed To The Internet

Change the above SSH rule with:

  • 3389: RDP

  • 5900: TigerVNC, TightVNC, RealVNC

"data.aws.dstport": {
    "value": [3389, 5900],
    "boost": 1
}

Inbound Database Ports Exposed To The Internet

Change the above SSH or RDP rule with:

  • 3306: MySQL Server

  • 5432: PostGreSQL

  • 1433: Microsoft SQL Server

"data.aws.dstport": {
    "value": [3306, 5432, 1433],
    "boost": 1
}

Port Scan Detection Trigger

Here we detect a single source IP connecting to multiple high-value ports in a short window—consistent with nmap-style scanning in the open_vpc discovery phase.

Rule Description In Layman Terms

"Alert when the same source IP has triggered our high-value port rules at least four times within 120 seconds."

One IP hitting SSH, then RDP, then MySQL in quick succession is a strong indicator of a port scan.

All we have to do is modify the trigger to be above or equal to whatever we decide to choose.

For example:

return ctx.results[0].hits.total.value >= 4;

Would trigger if the value is above or equal to 4 based on the run frequency interval, so within the last 1 minutes.

Verify Detections

We won't be able to use the open-vpc CloudFormation stack. This is due to the settings we used to configure the VPC Flow Logs.

If you can recall, we set up a S3 data lake bucket, which collects our VPC flow logs from project-x-vpc. The CloudFormation stack creates an entirely new VPC.

We can "simulate" this attack by creating a new EC2 instance with any of the above ports opened.

Create EC2 Instance

We won't walk though this.

Create a new EC2 intance, under the project-x-vpc. Ensure it is deployed in the public subnet.

Attach a new or pre-defined security group with whatever port you want opened.

Remember, the EC2 instance must also have a service running with the exposed port.

We recommend default port 22 since you will not have to log into the ec2 instance.

Generate Test Traffic (Open VPC Scenario)

From an external machine (or [project-x-attacker]), run:

# Scan high-value ports
nmap -p 22,80,443,3306,5432,3389 $PUBLIC_IP

# Or simple connectivity checks
nc -zv $PUBLIC_IP 22
nc -zv $PUBLIC_IP 3389

Wait 5–15 minutes for VPC Flow Logs to be written to S3 and ingested by Wazuh.

Click To Zoom
(Click to zoom)

View Alerts

Navigate to Alerting.

You should see a new alert generate with the opened port in question.

You should see alerts for inbound SSH, RDP, or database traffic from external IPs when the open-vpc stack is deployed and the rules are firing.