
Ricognizione di Active Directory e audit di sicurezza in sola lettura su ADWS (net.tcp/9389), in Go
adit è uno strumento single-binary per la ricognizione di Active Directory e per l'audit di sicurezza in sola lettura che comunica con un Domain Controller tramite ADWS (Active Directory Web Services, TCP/9389) invece che tramite LDAP.
Un adit è l'ingresso orizzontale di una miniera — la via d'accesso silenziosa. Interrogare AD tramite ADWS anziché LDAP/389 significa che il traffico è incapsulato in WCF net.tcp, SOAP in binary-XML su una porta non comune, quindi è molto meno probabile che venga ispezionato, filtrato o firmato rispetto al classico LDAP — pur restituendo gli stessi dati della directory. adit implementa l'intero stack del protocollo ADWS in Go, senza dipendenze runtime esterne.
┌────────────┐ net.tcp/9389 ┌──────────────┐
│ adit │ ───────────────▶ │ ADWS on DC │ ──▶ local LDAP
│ (Linux) │ NMF · NNS · │ (port 9389) │
│ │ NBFSE · SOAP └──────────────┘
└────────────┘
adit è uno strumento difensivo/di audit e per valutazioni autorizzate. Eseguilo solo su directory che sei autorizzato a valutare.
| Capacità | Dettagli |
|---|---|
| Trasporto | ADWS su WCF net.tcp (TCP/9389) — framing MC-NMF, handshake MS-NNS, binary XML MC-NBFS/NBFSE, SOAP WS-Enumeration/WS-Transfer |
| Autenticazione | NTLMv2 (sign + seal) e Kerberos (ccache / keytab / password; GSS sigillato RFC 4121) |
| Collector di recon | 31 moduli (vedi sotto) → CSV per modulo |
| Reporting | Workbook XLSX multi-foglio formattato + dashboard HTML autonoma (ricerca/ordinamento, badge di severità, scroll-spy) |
| Audit di sicurezza | 27 regole in sola lettura (incl. ADCS ESC1–4/9) → JSON ordinato per severità, mostrato anche nella dashboard |
| Proxy / jump host | HTTP CONNECT, SOCKS5/5h, SOCKS4/4a (con auth proxy + DNS remoto) |
| Paging | Paging Pull lato server WS-Enumeration, dimensione pagina configurabile |
| Reporting offline | Ricostruisci XLSX/HTML dai CSV raccolti in precedenza, senza DC |
| Dipendenze | Go puro; nessuna libreria LDAP, nessun .NET, nessun servizio esterno |
forest, domain, trusts, sites, subnets, schemahistory, dcs,
users, userspns, groups, computers, computerspns, ous, gpos,
gplinks, passwordpolicy, fgpp, dnszones, dnsrecords, kerberoastable,
asreproastable, krbtgt, adcs, cas, laps, protectedgroups,
groupmembers, gmsa, dmsa, printers, bitlocker
ADCS (adcs) segnala ESC1–ESC4/ESC9; laps riporta chi può leggere ciascuna password; protectedgroups esegue l'audit dei Protected Users. Esegui adit -list-modules per l'elenco aggiornato.
-audit esegue 27 regole in sola lettura. I findings riportano un id regola, severità, oggetti interessati, evidenze e remediation, e vengono scritti in Adit-Audit.json (e, se combinati con -collect, in una sezione "Audit Findings" che guida la dashboard). Il motore non legge mai i valori degli attributi segreti (LAPS / gMSA / BitLocker), anche se i collector di recon possono farlo.
| Regola | Severità | Cosa segnala |
|---|---|---|
| AD-DOM-010 | Critical | Diritti DCSync (replication) detenuti da un principal non-Tier-0 |
| AD-ACL-001/005/006/007/011–016 | Critical | Controllo pericoloso (GenericAll/Write, WriteDACL/Owner, ForceChangePassword, Write SPN / KeyCredentialLink / member / AllowedToAct) su un oggetto privilegiato |
| AD-SDH-001/002 | Critical | Controllo / owner inatteso di AdminSDHolder |
| AD-CS-001 | Critical–Medium | ESC1 — il template di certificato consente il subject fornito dall'enrollee |
| AD-CS-002 | Critical–Medium | ESC2 — template di certificato Any-Purpose / senza EKU |
| AD-CS-003 | High–Medium | ESC3 — template Certificate Request Agent |
| AD-CS-004 | High | ESC4 — controllo di accesso debole su un template di certificato |
| AD-CS-009 | High | ESC9 — il template di certificato manca dell'estensione di sicurezza |
| AD-CS-005 | Critical/High | ESC5 — controllo pericoloso di un oggetto PKI (NTAuthCertificates, CA store, oggetto CA) |
| AD-CS-006 | Info | AD CS presente — ESC6/ESC7/ESC8 richiedono verifica a livello host (non osservabili via ADWS) |
| AD-DOM-008 | High | Crittografia reversibile delle password abilitata a livello di dominio |
| AD-USR-001 | High | Pre-autenticazione Kerberos disabilitata (AS-REP roastable) |
| AD-USR-009 | High | L'account usa solo crittografia DES |
| AD-CMP-006 | High | Delegation non vincolata su un non-DC |
| AD-KCL-001 | High | Key Credential (shadow credential) su un account privilegiato |
| AD-KRB-001 | High | La password di krbtgt è obsoleta |
| AD-DOM-005 | Medium | Machine Account Quota > 0 (qualsiasi utente può aggiungere computer) |
| AD-USR-002 | Medium | Service account Kerberoastable (High se privilegiato) |
| AD-USR-005 | Medium | PASSWD_NOTREQD impostato |
| AD-USR-006 | Medium | La password di un account privilegiato non scade mai |
| AD-USR-011 | Medium | La password di un account privilegiato è obsoleta |
| AD-CMP-008 | Medium | Resource-based constrained delegation configurata |
| AD-CMP-012 | Medium | Sistema operativo legacy / non supportato |
| AD-GRP-009 | Medium | Foreign security principal in un gruppo privilegiato |
| AD-GRP-020 | Medium | Appartenenza privilegiata nascosta tramite primaryGroupID |
| AD-TRU-001/003 | High/Medium | Trust senza SID filtering / con SID history |
| AD-DNS-003/004 | Medium/Low | Record WPAD / ISATAP presente |
| AD-CMP-011 | Low | Account computer obsoleto |
| AD-INT-005 | High | sIDHistory contiene un SID privilegiato |
Le soglie sono regolabili: -krbtgt-max-age, -priv-pwd-max-age, -stale-days.
Nota ADCS: ESC1–ESC5 ed ESC9 sono valutati dagli oggetti AD via ADWS. ESC6 (
EDITF_ATTRIBUTESUBJECTALTNAME2), ESC7 (ACL dei ruoli CA) ed ESC8 (web enrollment / NTLM relay) risiedono nel registro/endpoint HTTP dell'host CA e non sono osservabili via ADWS —AD-CS-006segnala che esiste una CA così che possano essere verificati sull'host (ad es. con Certipy).
Richiede Go 1.26+. Nessun'altra dipendenza di build.
# Build the binary
go build -o adit ./cmd/adit
./adit -version
# …or run without installing
go run ./cmd/adit -h
# Cross-compile release archives for linux/windows/darwin (amd64+arm64) into dist/
bash scripts/build-release.sh
-fqdn deve essere il vero FQDN del DC (non il suo IP): l'header SOAP To di ADWS viene confrontato con l'endpoint dall'AddressFilter di WCF. Trovalo con, ad esempio, nslookup -type=SRV _ldap._tcp.dc._msdcs.<domain> <dc-ip>.
adit -dc <host> -fqdn <dc-fqdn> -d <DOMAIN> -u <user> -p <pass> [flags]
# RootDSE handshake only (verifies auth + the full protocol stack)
adit -dc 10.0.0.10 -fqdn dc01.example.local -d EXAMPLE.LOCAL -u user -p 'pass'
# Run every collector -> ./report/CSV-Files/*.csv + Adit-Report.{xlsx,html}
adit -dc 10.0.0.10 -fqdn dc01.example.local -d EXAMPLE.LOCAL -u user -p 'pass' \
-collect all -o ./report
# A subset of collectors
adit -dc 10.0.0.10 -fqdn dc01.example.local -d EXAMPLE.LOCAL -u user -p 'pass' \
-collect users,groups,computers,kerberoastable