Cloud-Based Honeypot: Analyzing RDP Attacks
In this project, we are setting up an Azure Honeypot Lab using Microsoft Sentinel to detect and analyze failed RDP login attempts on a Windows host. By intentionally exposing a Virtual Machine to the internet, we can gather data on where attacks are originating from and visualize them on a world map.
Goal: Transform raw Windows Event Logs into a visual Threat Intelligence Map.
Demo
Above: A timelapse of the live attack map populating over a 24-hour period.
Lab Architecture Overview
The lab consists of three main components:
- Windows 10 VM: Acts as the honeypot.
- Log Analytics Workspace: Ingests the custom logs.
- Microsoft Sentinel: Serves as the SIEM for visualization.
The Workflow
- Attackers attempt to RDP into the exposed VM.
- Windows records these as Event ID 4625 (Failed Logon).
- A custom PowerShell script extracts the IP, Username, and Timestamp.
- The script queries a Geolocation API to get the physical location of the IP.
- Data is written to a custom log file (
failed_rdp.log) and sent to Azure Sentinel.
Prerequisites & Setup
Before running the script, ensure you have the following:
- Azure Resources: A Virtual Machine, Network Security Group (allowing RDP), and a Log Analytics Workspace.
- IP2Location API Key: You will need a free API key to enrich IP addresses with geo-data. Get your API Key here.
The PowerShell Exporter
This PowerShell script is the heart of the honeypot. It monitors the Windows Event Viewer for security events, specifically looking for failed login attempts.
Key Configuration: Set your$API_KEYvariable and ensure the$LOGFILE_PATHis accessible (e.g.,C:\ProgramData\failed_rdp.log).
# Partial Script Snippet for Context
$API_KEY = "YOUR_API_KEY_HERE"
$LOGFILE_NAME = "failed_rdp.log"
$LOGFILE_PATH = "C:\ProgramData\$($LOGFILE_NAME)"
# Filter for Failed RDP events (EventID 4625)
$XMLFilter = @'
<QueryList>
<Query Id="0" Path="Security">
<Select Path="Security">
*[System[(EventID='4625')]]
</Select>
</Query>
</QueryList>
'@
You can download the full script here.
How the Script Works
- Event Monitoring: An infinite loop continuously checks Windows Event Viewer for Event ID
4625. - Data Extraction: When a failed login is found, the script pulls the
Source IP($event.properties[19]),Username, andTimestamp. - Geolocation Enrichment: The script pauses for 1 second (to avoid rate limits) and queries the ipgeolocation.io API to get the Latitude, Longitude, and Country of the attacker.
- Logging: The enriched data is appended to
failed_rdp.login a format that Azure can easily parse.
Ingesting & Querying Data in Azure
Once the log file is being populated on the VM, we configure the Log Analytics Workspace to ingest this custom log.
1. Parsing the Custom Log
Use the following KQL (Kusto Query Language) query to parse the raw data fields from the custom log file:
FAILED_RDP_GEO_CL
| extend username = extract(@"username:([^,]+)", 1, RawData),
timestamp = extract(@"timestamp:([^,]+)", 1, RawData),
latitude = extract(@"latitude:([^,]+)", 1, RawData),
longitude = extract(@"longitude:([^,]+)", 1, RawData),
sourcehost = extract(@"sourcehost:([^,]+)", 1, RawData),
state = extract(@"state:([^,]+)", 1, RawData),
label = extract(@"label:([^,]+)", 1, RawData),
destination = extract(@"destinationhost:([^,]+)", 1, RawData),
country = extract(@"country:([^,]+)", 1, RawData)
| where destination != "samplehost"
| where sourcehost != ""
| summarize event_count=count() by timestamp, label, country, state, sourcehost, username, destination, longitude, latitude
2. Visualizing the Attack Map
To build the visual map in Microsoft Sentinel Workbooks, we use a similar query but summarize by location for the map render:
...
| summarize event_count=count() by latitude, longitude, sourcehost, label, destination, country
Results & Analysis
After leaving the honeypot running for 24 hours, the map populates with live attack data. The visualization below shows the volume and origin of RDP brute-force attempts.
Top Attack Sources
The data revealed significant activity from specific regions. Here is a breakdown of the top sources captured during the test run:
| Location | No. of Attempts | Common IPs |
|---|---|---|
| Poland | 16.4K | 149.50.96.98 |
| Mozambique | 5.88K | 160.242.36.216 |
| China | 4.17K | 125.75.66.99 |
| Netherlands | 3.85K | 92.63.197.23 , 185.170.144.3 , 84.84.121.37 |
| UK | 1.61K | 80.94.95.215 |
| Korea | 1016 | 115.92.155.19 , 122.202.246.213 |
| India | 709 | 203.192.237.115 , 103.119.179.133 , 125.18.138.42 |
| Serbia | 358 | 109.92.111.135 |
| Nepal | 340 | 110.44.116.60 |
| Sudan | 220 | 41.209.126.101 |
| USA | 140 | 185.243.96.107 , 67.205.146.203 |
| Russia | 64 | 185.39.19.42 |
| Ukraine | 47 | 185.243.96.107 |
| Luxembourg | 30 | 158.64.24.12 |
Note: It is fascinating to see over 16,000 attempts originating from a single IP in Poland within a 24-hour window.
Challenges & Lessons Learned
Running this honeypot in a real cloud environment taught me several practical lessons about Azure management and API integration:
- API Rate Limiting: The script initially failed to log all attacks because the free tier of the Geolocation API has a rate limit (approx. 1,000 requests per day). I had to ensure the script included a
Start-Sleepcommand to pause execution between queries to avoid hitting the 429 "Too Many Requests" error. - Azure Cost Management: Leaving a Virtual Machine and a Log Analytics Workspace running can incur unexpected costs. I learned the importance of setting up "Auto-Shutdown" on the VM and monitoring the data ingestion volume, as ingesting thousands of logs per day can impact the Azure bill.
- KQL Optimization: When you have over 16,000 logs from a single source (like the IP from Poland), the map visualization can become cluttered or slow to render. I learned to use
summarizeefficiently in KQL to group data by country or region before rendering the map points.
Conclusion
This project demonstrates how easily a Windows machine exposed to the internet attracts malicious traffic. By integrating PowerShell scripting with Azure Sentinel, we can transform noise into actionable threat intelligence.