Security News

Cybersecurity news aggregator

INFO News Huntress

The 60ms Window: How Event 5156 Solves the ADWS Attribution Problem

  • What: Research on Event 5156 helps with source IP attribution in ADWS
  • Impact: Improves detection of malicious activity in Active Directory
Read Full Article →

Home Blog From Code to Coverage (Part 5B): Event 5156 Correlation: Proving Source IP Attribution Is Possible Published: April 9, 2026 From Code to Coverage (Part 5B): Event 5156 Correlation: Proving Source IP Attribution Is Possible By: Andrew Schwartz The BloodHound Slack challenge Coincidentally, as I was drafting my post on the ADWS blind spot (originally scoped to be part 6, but now Part 5A ), I observed an interesting conversation take place in the BloodHound Slack #red-team channel. The conversation that followed set the stage for this research, and ended up leading me to decide to split Part 6 into two separate posts. The original exchange It started when User 1 asked about ADWS detection: "Hi guys, what's your preferred way of opsec safe AD enum? ADSI vs ADWS? And what's your experience with detection of adws on the dc side? Eg when using soapy? ADSi has been very reliable for us, also in very mature environments. I would love to hear more about adws enum." User 2 responded with his preference for ADWS and explained the detection challenges: "My preferred way is using ADWS for AD collection but I'm a bit biased lol 😅 But the name of the game when performing stealthy collection of any type is all about using constrained and unique queries. Specifically doing collection through ADWS has a large number of opsec benefits which depending on how detections are written can completely bypass some LDAP oriented detections. As for the best way of detecting ADWS, probably SACL canaries." User 2 then explained the core attribution problem: "The main thing differentiating the two protocols is with common LDAP diagnostic logging the host/device the collection appears to be coming from in the logs is always the DC the ADWS query is executed on due to the ADWS services interaction with the LDAP service on loopback, and detailed logging for the ADWS service is very lacking and usually not enabled." Charlie Clark asked if correlation was possible with more logs: "absolutely, but it's still possible to determine for adws requests, right? it's just it requires correlating more logs?" User 2's response: "Nope, not really. I've not found a way to correlate the originating host whatsoever. The only way to derive the originating host is through netsession enumeration, but its even harder with SOAPy because you can proxy in the traffic from a non-windows session." Charlie pushed back: "surely you could with a network event? 5156?" User 2's full response outlined the challenges: "Yeah you could theoretically identify the originating host with 5156 but thats just a basic network connection and usually tuned down due to the large amount of those events generated. Big identity solutions like MDI usually don't alert for collection on those types of events to my understanding due to the amount of normal traffic. You could detect it with traffic to 9389 (ADWS) but there's an even bigger problem there, all of RSAT uses ADWS. So sysadmins doing normal operations would trigger false positives. So you could figure it out during triage but it would be tough but alerting is very difficult" Why Event 5156 wasn't a random suggestion When I saw Charlie suggest Event 5156, I knew immediately that he was onto something. This wasn't a shot in the dark; Charlie, Jonathan Johnson, and I had collaborated on Event 5156 correlation before. Prior work: Jonathan Johnson's RPC Research - Jonny's SpecterOps 2022 paper, "RPC for Detection Engineers" , had demonstrated the power of Event 5156 for correlating network connections with service activity. Our Collaborative Post - Charlie, Jonny, and I had published "The Client Server Relationship - A Match Made in Heaven" , where we showed exactly how to use Event 5156 for client-server correlation and attribution. So when User 2 said 5156 correlation was “theoretically” possible but impractical, I knew the technique worked. The question was whether it would work specifically for ADWS. Challenge accepted. The hypothesis User 2 raised valid concerns: Event 5156 generates high volume RSAT tools create false positives Correlation is difficult But I hypothesized that: Event 5156 is already being collected by most enterprise SIEMs Pattern detection in 1644 (like [all_with_list] , SDflags:0x7 , (!(FALSE)) ) solves the false positive problem Timestamp correlation with a tight window could work Phase 1: Understanding the event flow In Part 5A we showed how ADWS hides the attacker’s IP from network sensors and Event 1644—the network sees only an encrypted blob on port 9389, and the LDAP log shows [::1] as the client. Here’s the full event sequence that makes attribution possible anyway. Event 5156 is the missing piece. It comes from the Windows Filtering Platform (WFP) and hits the Security event log every time a network connection is permitted. It’s become one of my favorite events for correlation work because it records the application that owns the connection, not just the port. So instead of seeing generic svchost.exe , you see microsoft.activedirectory.webservices.exe. It’s on by default under the Filtering Platform Connection audit subcategory, so no extra configuration is needed. When a remote host connects to ADWS on port 9389, Event 5156 captures the inbound connection with the real source IP. That happens before ADWS translates the request into an internal LDAP call, which is the step that swaps the real IP for localhost. Figure 1: Event 5156 (Security Log): The Windows Filtering Platform captures the inbound ADWS connection with the real source IP before the request is translated internally. Figure 2: Event 1138 (AD Web Services Log): ADWS logs the new connection with the client's real IP and a unique InstanceId that ties the session to subsequent events. Figure 3: Event 1644 (Directory Service Log): The internal LDAP query shows localhost as the client—the real source IP is gone, but the user context and query details are preserved. This is the external connection that provides source IP attribution. Phase 2: Port-based correlation Event 1644 shows the client as [::1]:60983 (localhost with ephemeral port). If we could find an internal Event 5156 showing ADWS connecting to LDAP on that same port, we could chain: External 5156 → Internal 5156 (matching port) → 1644. Running SOAPy from the Linux box (10.1.1.13) and checking the logs: Event 1644: Client: [::1]:60983 User: MARVEL\loki Filter: ( & (objectClass=user) ... ) Internal 5156 events found: 03:54:46.406 | ::1:61532 03:53:46.393 | ::1:61522 03:52:46.380 | ::1:61514 The ports don’t match. Event 1644 shows port 60983, but the internal 5156 events show 61532, 61522, and so on. Port 60983 is a persistent LDAP connection ADWS established long before the test. The original 5156 for that connection had already rolled out of the Security log. New queries reuse this existing connection — no new 5156 is created for each query. Port-based correlation only works in a SIEM where the original 5156 (when the persistent connection was first established) is still retained. On a live DC query, it may have rolled out. Phase 3: Timestamp-based correlation Port-based correlation failed, but the events still happen in sequence with predictable timing. Even if the persistent connection’s original 5156 has rolled out of the log, the external 5156 that fired for the current query is still there — timestamped within milliseconds of Event 1644. The hypothesis: correlate by time window. External 5156 → [ADWS processing] → Event 1644 ~60–80ms Same SOAPy attack, checking timestamps: External 5156: Time: 03:53:28.407 Source IP: 10.1.1.13 Dest Port: 9389 Application: microsoft.activedirectory.webservices.exe Event 1644: Time: 03:53:28.469 Client: [::1]:60983 User: MARVEL\loki Filter: ( & (objectClass=user) (objectCategory=CN=Person,CN=Schema,CN=Configuration,DC=marvel,DC=local) ) Attributes: [all_with_list]nTSecurityDescriptor Controls: SDflags:0x7; Delta: 62ms Repeated testing across three runs: Test Run External 5156 Event 1644 Delta Run 1 03:52:22.256 03:52:22.339 83.2ms Run 2 03:53:28.407 03:53:28.469 61.2ms Run 3 03:55:25.275 03:55:25.341 65.8ms Consistent ~60-80ms window across all three runs. The processing delay between external connection and LDAP query execution is stable enough to correlate events. Phase 4: Building the detection script With timestamp correlation confirmed as reliable, the next step was building a script that could do this automatically — collecting the relevant events, attempting port-based correlation first, then falling back to the timing window. Running Get-ADWSAttribution.ps1 during active SOAPy enumeration: Figure 4: Get-ADWSAttribution.ps1 correlating Event 5156 → 1644 to attribute LDAP queries back to their source IP, catching MARVEL\loki mid-BloodHound enumeration. Source IP 10.1.1.13 correctly attributed to all three queries. The real-time monitor mode catches it as it happens: Figure 5: Three events. One attacker. Event 5156 tells you who connected. Event 1138 tells you ADWS proxied it. Event 1644 tells you what they were after. Phase 5: The 5156 reality check The first objection to any 5156-based detection is volume, the concern that it’s tuned down or disabled in most environments. Let's check: auditpol /get /subcategory: "Filtering Platform Connection" Filtering Platform Connection Success Event 5156 is on by default. It’s part of Windows Filtering Platform auditing that ships enabled out of the box. The volume concern is real, but it’s about retention, not availability. Every network connection generates a 5156, so on a busy DC, the Security log fills fast, and old events get overwritten. The fix is SIEM. Most enterprise environments already forward Security logs to a SIEM, which means the data is retained for days or weeks. Environment 5156 Availability Correlation Method Live DC query May have rolled out TIMESTAMP (probabilistic) SIEM (Splunk/Sentinel) Retained for days/weeks PORT (deterministic) or TIMESTAMP Forensic EVTX backup If captured

Share this article