daemon-sec-cheatsheet

The cheatsheet vault for operators: AD, enumeration, exploitation, priv-esc, web, DFIR
git clone https://git.daemon-sec.xyz/daemon-sec-cheatsheet.git
Log | Files | Refs | README | LICENSE

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/)