Windows Brute Force Detection

Home SOC Lab Pack · Lab 1, built on the Home SOC foundation

Solo build · Wazuh correlation rule · Hydra RDP brute force simulation · MITRE ATT&CK

The scenario

Meridian Logistics Group represents a common and dangerous gap in mid-size organisations: infrastructure provisioned for a specific business need, RDP access for a contractor, that outlives its purpose and its oversight. The jump host had no visibility into authentication activity at all, so a sustained brute-force campaign of roughly 4,000 attempts could run undetected. The brief called for detection within 15 minutes of brute-force success, with supporting evidence, not just an alert that fires, but a documented chain from raw log to dashboard to incident summary.

The approach: enable the right log sources, write detection logic that recognises the specific pattern of high-frequency failed logons followed by a success from the same source, author that same logic as a vendor-neutral Sigma rule and its Elastic equivalent, then validate the entire pipeline against a real simulated attack and a credential-reuse pivot toward the domain controller.

Network architecture

Built directly on the four-endpoint Home SOC foundation: HOM-PC-L002 as the attack source, HOM-PC-W001 as the exposed RDP jump host, HOM-SVR-W004 as the pivot target, and HOM-PC-L003 running the Wazuh Manager that correlates and alerts on the whole chain.

Network architecture diagram showing the attack source, Windows endpoints, and Wazuh manager used in the brute force detection lab
Lab topology: attack source, jump host, pivot target, and the Wazuh manager correlating detection across all three.

Technology stack

Confirmatory tests: telemetry before the attack

Before simulating anything, both Windows endpoints were confirmed sending logon telemetry end to end. On HOM-PC-W001, a deliberately incorrect runas credential was submitted against the local Administrator account, followed by a correct one. The failed logon was flagged by rule 60122 at level 5; a successful authentication followed 5.2 seconds later, triggering a tight, correctly ordered cluster, privilege assignment (67028), account changed (60110).

Triggering a failed logon in PowerShell as Administrator on HOM-PC-W001
Triggering a failed logon in PowerShell as Administrator to verify the agent's response (HOM-PC-W001).
Failed logon confirmed on HOM-PC-W001
Account failed logon confirmed.
Triggering a successful logon in PowerShell as Administrator on HOM-PC-W001
Triggering a successful logon to verify the agent's response, using the correct login password.
Wazuh dashboard showing the logon failure alert for HOM-PC-W001
Logon failure alert (rule 60122) on the Wazuh dashboard.
Wazuh dashboard showing the successful logon event cluster for HOM-PC-W001
The correctly ordered success cluster following the failed logon: special privileges assigned (67028), account changed (60110).

The same confirmatory test was repeated on HOM-SVR-W004, with a successful authentication following 43 seconds later, correctly classified by rule 60118 with the same expected supporting events.

Triggering a failed logon in PowerShell as Administrator on HOM-SVR-W004
Triggering a failed logon to verify the agent's response (HOM-SVR-W004).
Triggering a successful logon in PowerShell as Administrator on HOM-SVR-W004
Triggering a successful logon to verify the agent's response.
Account login failed confirmation on HOM-SVR-W004
Account login failed confirmation.
Account login successful confirmation on HOM-SVR-W004
Account login successful confirmation.
Wazuh dashboard login failure and success alerts summary for HOM-SVR-W004
Login failure/success alerts summary on the Wazuh dashboard for HOM-SVR-W004.

Custom detection rule deployment

local_rules.xml was edited to add the lab1_bruteforce group: rule 100210 (the failure-threshold base) and rule 100211 (the brute-force success correlation, 8+ failed logons followed by a success from the same source). Structure was verified with cat -A before validation. A wazuh-logtest attempt against rule 100211 returned the generic rule 1002 (unmatched) rather than 100211, a known limitation, manually pasted logs lack the eventchannel location metadata the rule depends on, so this was treated as expected rather than a real failure and validation moved to a live restart instead.

local_rules.xml edited to add the lab1_bruteforce rule group
local_rules.xml edited to add the lab1_bruteforce group (rules 100210, 100211), structure verified via cat -A.
wazuh-logtest returning the generic unmatched rule 1002 instead of 100211
wazuh-logtest correlation test returning rule 1002 (unmatched) due to missing eventchannel metadata in a manually pasted log, an expected limitation of this test method.
Wazuh manager service restarted cleanly with the new rule group loaded
wazuh-manager restarted cleanly, status active (running), to load the new lab1_bruteforce rule group.
Rule 100211 confirmed present and correctly configured in the Wazuh dashboard Rules management view
Rule 100211 confirmed live in the Wazuh dashboard's Rules management view, level 12, correctly described and grouped.

Attack preparation

Hydra was installed on the attack source, HOM-PC-L002. The jump host's built-in Administrator account, disabled by default on Windows 11, was enabled with a known credential, and RDP was confirmed running with the correct inbound firewall rule after an initial check found the service stopped.

Hydra version confirmed on HOM-PC-L002
Hydra installed on HOM-PC-L002, version confirmed via hydra -h.
Hydra installation completed on the attack source
Hydra installation confirmed complete on the attack source.
Local RDP port 3389 reachability confirmed via PowerShell Test-NetConnection on HOM-PC-W001
Local port 3389 reachability on HOM-PC-W001 confirmed via PowerShell Test-NetConnection.
nmap confirming RDP port 3389 open on HOM-PC-W001 from the attack source
Network-level RDP reachability from HOM-PC-L002 to HOM-PC-W001 confirmed via nmap: port 3389/tcp open, ms-wbt-server.

A custom password wordlist was built for the Hydra simulation, deliberately incorrect entries followed by the known correct Administrator credential, then trimmed to 8 invalid entries plus 1 valid entry to stay within the jump host's lockout threshold of 10 while still meeting rule 100211's frequency requirement of 8.

Hydra password list created and verified on HOM-PC-L002
Hydra password list prepared on HOM-PC-L002: 8 invalid passwords followed by the valid Administrator credential.

Brute-force attack execution

From HOM-PC-L002, Hydra ran the prepared password list against HOM-PC-W001's RDP service, and the resulting activity was mapped against the MITRE ATT&CK framework alongside the live Wazuh alerts.

Hydra executing the RDP brute force attack from HOM-PC-L002 against HOM-PC-W001
Hydra executing the RDP brute-force simulation from HOM-PC-L002 against HOM-PC-W001.
Wazuh alerts generated during the simulated brute force attack
Wazuh alerts generated during the attack, repeated authentication failures against the target.
Wazuh alert cluster view during the brute force attack
The alert cluster building as the attack progresses.
Simulated brute force activity mapped to the MITRE ATT&CK framework, overview
The simulated brute-force activity mapped to its MITRE ATT&CK technique.
MITRE ATT&CK mapping detail for the brute force technique observed
MITRE ATT&CK mapping detail, attack behaviour and detection context.
Wazuh dashboard alerts summary for the initial brute force simulation
Wazuh alerts summary for the attack: repeated failed logons followed by a successful authentication.

Root cause: a rule priority collision, found and fixed

Rule 100211 didn't fire on this first live attack. The root cause: Wazuh credited the built-in rule 92657 (level 6, a generic pass-the-hash/RDP detection) as the primary classification for the successful logon event, so the custom rule, conditioned on <if_sid>100210</if_sid>, never saw a matching parent to correlate against. The fix: change the trigger condition from a specific rule SID to a broader group context, <if_group>authentication_success</if_group>, so the correlation fires regardless of which specific built-in rule classifies the successful logon first.

Rule 100211 configuration before the fix, triggered on a specific SID
Rule 100211 before editing: triggered on a specific SID (100210), which the built-in rule 92657 was pre-empting.
Rule 100211 configuration after the fix, triggered on the authentication_success group
Rule 100211 after editing: triggered on the authentication_success group context instead of a single SID.
wazuh-logtest XML validation confirming local_rules.xml parses cleanly after the fix
wazuh-logtest re-run post-fix: no XML parse errors, ruleset loads cleanly through to the end of the file.
wazuh-manager restarted successfully with the corrected rule 100211 live
wazuh-manager restarted with the corrected rule 100211 live, ready for re-testing.

Re-run: rule confirmed firing against a live attack

The Hydra attack was re-run from HOM-PC-L002 against HOM-PC-W001's RDP using the same 9-entry wordlist. Rule 100211 fired at level 12, correctly identifying the full pattern, 8+ failed logons via rule 60122, followed by a successful logon from the same source IP, targeting Administrator@HOM-PC-W001, within milliseconds of the successful logon. The priority collision with rule 92657 was confirmed resolved, validated end to end against a genuine, live RDP brute-force attack rather than a synthetic test.

Hydra brute force attack re-run from HOM-PC-L002 after the rule 100211 fix
Hydra attack re-run from HOM-PC-L002 following the rule 100211 fix.
Wazuh dashboard confirming rule 100211 fired at level 12 against the live re-run attack
Rule 100211 fired at level 12, correctly correlating the failure burst and the successful logon from the same source, confirmed on the Wazuh dashboard.

Simulated credential pivot: HOM-PC-W001 to HOM-SVR-W004

The brief's scenario has the attacker pivoting toward the domain controller using the same credentials after the jump host is compromised, lateral movement through valid accounts. A matching Administrator password was set on HOM-SVR-W004, RDP reachability confirmed, and the pivot executed via xfreerdp from HOM-PC-L002 using the password already compromised in the brute-force phase.

Matching Administrator password set on HOM-SVR-W004
Matching Administrator password set on HOM-SVR-W004 to simulate credential reuse.
RDP reachability to HOM-SVR-W004 confirmed via PowerShell
RDP reachability to HOM-SVR-W004 confirmed via PowerShell.
nmap confirming RDP port 3389 open on HOM-SVR-W004 from the attack source
Network-level RDP reachability from HOM-PC-L002 to HOM-SVR-W004 confirmed via nmap: port 3389/tcp open, ms-wbt-server.
RDP listener confirmed active on HOM-SVR-W004 via netstat
RDP listener on HOM-SVR-W004 confirmed active via netstat, listening on all interfaces after a service restart cycle.
xfreerdp executed from HOM-PC-L002 to pivot into HOM-SVR-W004
xfreerdp executed from HOM-PC-L002, authenticating to HOM-SVR-W004 as Administrator using the password compromised on HOM-PC-W001.
Credential-reuse pivot simulation executed successfully from HOM-PC-L002 to HOM-SVR-W004
Credential-reuse pivot simulation executed: a single successful authentication with no preceding failures, matching real lateral-movement behaviour.
FreeRDP session window showing an active Administrator session on HOM-SVR-W004
The FreeRDP client window on HOM-PC-L002, an active Administrator PowerShell session on the HOM-SVR-W004 desktop, visual confirmation the pivot succeeded.
Wazuh dashboard confirming detection of the credential reuse pivot via rules 92657 and 92653
Pivot detected: rule 92657 (level 6) and rule 92653 (level 3) both fired independently on the credential-reuse RDP logon, distinct coverage from the custom brute-force rule used on the jump host.

Sigma rule and Elastic query documentation

The same detection logic proven working in Wazuh was authored as a vendor-neutral Sigma rule and documented as its Elastic equivalent. One honest technical note: Sigma's correlation types, value_count for the frequency threshold and temporal_ordered for the failure-then-success sequence, couldn't express the full logic as a single rule. Converting through sigma-cli with the Wazuh backend produced two separate native rules, a counter and a sequence, which had to be manually merged. The native Wazuh configuration, combining a frequency threshold, sequence tracking, and same-source correlation in one rule, turned out more expressive than either standard could cleanly represent on its own. Elastic Security enforces the same structural split: the frequency threshold maps to a built-in Threshold rule type, and the ordered sequence to a separate EQL sequence query, not raw KQL.

Challenges and workarounds

Incident summary

Scope: Meridian's jump host (HOM-PC-W001) had an exposed RDP service with no logon monitoring, a legacy of contractor remote access that outlived its purpose. This engagement built, tested, and validated detection for exactly that gap.

Detection logic: a custom Wazuh correlation rule (ID 100211) detects eight or more failed RDP logons followed by a successful logon from the same source IP, within a 120-second window.

Results: Phase 1, brute force (HOM-PC-L002 → HOM-PC-W001), Hydra ran a 9-entry credential list against RDP; rule 100211 fired at level 12 within milliseconds of the successful logon. Phase 2, lateral movement (HOM-PC-L002 → HOM-SVR-W004), using the credential compromised in Phase 1, a single clean RDP authentication simulated a valid-account pivot, detected independently by Wazuh's built-in anomalous-logon rules.

False positives: two unrelated alerts on HOM-SVR-W004 during testing were investigated and confirmed as false positives rather than indicators of compromise, a "possible PrintNightmare" alert traced to the legitimate Terminal Services Easy Print driver auto-installed by FreeRDP's printer redirection, and a "PowerShell created executable in Windows root" alert traced to PowerShell's own internal script-policy validation artifacts.

Recommended containment:

The full project report, including the Sigma and Elastic rule YAML, is documented on Notion.

View full report on Notion →