Reconocimiento de Active Directory y auditoría de seguridad de solo lectura sobre ADWS (net.tcp/9389), en Go
adit es una herramienta de reconocimiento de Active Directory y de auditoría de seguridad de solo lectura, de binario único, que se comunica con un Controlador de Dominio a través de ADWS (Active Directory Web Services, TCP/9389) en lugar de LDAP.
Un adit es la entrada horizontal a una mina — la vía silenciosa de acceso. Consultar AD a través de ADWS en lugar de LDAP/389 significa que el tráfico está enmarcado como WCF net.tcp, SOAP de XML binario sobre un puerto poco común, por lo que es mucho menos probable que sea inspeccionado, filtrado o firmado que el LDAP clásico — mientras sigue devolviendo los mismos datos del directorio. adit implementa la pila completa del protocolo ADWS en Go, sin dependencias de runtime externas.
┌────────────┐ net.tcp/9389 ┌──────────────┐
│ adit │ ───────────────▶ │ ADWS on DC │ ──▶ local LDAP
│ (Linux) │ NMF · NNS · │ (port 9389) │
│ │ NBFSE · SOAP └──────────────┘
└────────────┘
adit es una herramienta defensiva/de auditoría y de evaluación autorizada. Ejecútala solo contra directorios que estés autorizado a evaluar.
| Capacidad | Detalles |
|---|---|
| Transporte | ADWS sobre WCF net.tcp (TCP/9389) — enmarcado MC-NMF, handshake MS-NNS, XML binario MC-NBFS/NBFSE, SOAP WS-Enumeration/WS-Transfer |
| Autenticación | NTLMv2 (sign + seal) y Kerberos (ccache / keytab / contraseña; GSS sellado RFC 4121) |
| Colectores de recon | 31 módulos (ver abajo) → CSV por módulo |
| Informes | Libro de trabajo XLSX multi-hoja con estilo + panel HTML autocontenido (búsqueda/ordenación, insignias de severidad, scroll-spy) |
| Auditoría de seguridad | 27 reglas de solo lectura (incl. ADCS ESC1–4/9) → JSON clasificado por severidad, también mostrado en el panel |
| Proxy / host de salto | HTTP CONNECT, SOCKS5/5h, SOCKS4/4a (con autenticación de proxy + DNS remoto) |
| Paginación | Paginación Pull de WS-Enumeration del lado del servidor, tamaño de página configurable |
| Informes sin conexión | Reconstruir XLSX/HTML a partir de CSVs previamente recolectados, sin necesidad de DC |
| Dependencias | Go puro; sin librería LDAP, sin .NET, sin servicios externos |
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) marca ESC1–ESC4/ESC9; laps informa quién puede leer cada contraseña; protectedgroups audita Protected Users. Ejecuta adit -list-modules para la lista actual.
-audit ejecuta 27 reglas de solo lectura. Los hallazgos llevan un id de regla, severidad, objetos afectados, evidencia y remediación, y se escriben en Adit-Audit.json (y, cuando se combina con -collect, una sección "Audit Findings" que encabeza el panel). El motor nunca lee valores de atributos secretos (LAPS / gMSA / BitLocker), aunque los colectores de recon sí pueden.
| Regla | Severidad | Qué marca |
|---|---|---|
| AD-DOM-010 | Crítica | Derechos DCSync (replicación) en manos de un principal que no es Tier-0 |
| AD-ACL-001/005/006/007/011–016 | Crítica | Control peligroso (GenericAll/Write, WriteDACL/Owner, ForceChangePassword, Write SPN / KeyCredentialLink / member / AllowedToAct) sobre un objeto privilegiado |
| AD-SDH-001/002 | Crítica | Control / propietario inesperado de AdminSDHolder |
| AD-CS-001 | Crítica–Media | ESC1 — la plantilla de certificado permite el sujeto proporcionado por el solicitante |
| AD-CS-002 | Crítica–Media | ESC2 — plantilla de certificado Any-Purpose / sin EKU |
| AD-CS-003 | Alta–Media | ESC3 — plantilla Certificate Request Agent |
| AD-CS-004 | Alta | ESC4 — control de acceso débil en una plantilla de certificado |
| AD-CS-009 | Alta | ESC9 — la plantilla de certificado carece de la extensión de seguridad |
| AD-CS-005 | Crítica/Alta | ESC5 — control peligroso de un objeto PKI (NTAuthCertificates, almacén de CA, objeto CA) |
| AD-CS-006 | Info | AD CS presente — ESC6/ESC7/ESC8 requieren verificación a nivel de host (no observable a través de ADWS) |
| AD-DOM-008 | Alta | Cifrado de contraseña reversible habilitado en todo el dominio |
| AD-USR-001 | Alta | Pre-autenticación Kerberos deshabilitada (AS-REP roastable) |
| AD-USR-009 | Alta | La cuenta usa solo cifrado DES |
| AD-CMP-006 | Alta | Delegación sin restricciones en un no-DC |
| AD-KCL-001 | Alta | Key Credential (credencial sombra) en una cuenta privilegiada |
| AD-KRB-001 | Alta | La contraseña de krbtgt está obsoleta |
| AD-DOM-005 | Media | Machine Account Quota > 0 (cualquier usuario puede unir equipos) |
| AD-USR-002 | Media | Cuenta de servicio Kerberoastable (Alta si es privilegiada) |
| AD-USR-005 | Media | PASSWD_NOTREQD establecido |
| AD-USR-006 | Media | La contraseña de la cuenta privilegiada nunca expira |
| AD-USR-011 | Media | La contraseña de la cuenta privilegiada está obsoleta |
| AD-CMP-008 | Media | Delegación restringida basada en recursos configurada |
| AD-CMP-012 | Media | Sistema operativo heredado / no soportado |
| AD-GRP-009 | Media | Principal de seguridad externo en un grupo privilegiado |
| AD-GRP-020 | Media | Pertenencia privilegiada oculta vía primaryGroupID |
| AD-TRU-001/003 | Alta/Media | Confianza sin filtrado de SID / con historial de SID |
| AD-DNS-003/004 | Media/Baja | Registro WPAD / ISATAP presente |
| AD-CMP-011 | Baja | Cuenta de equipo obsoleta |
| AD-INT-005 | Alta | sIDHistory contiene un SID privilegiado |
Los umbrales son ajustables: -krbtgt-max-age, -priv-pwd-max-age, -stale-days.
Nota sobre ADCS: ESC1–ESC5 y ESC9 se evalúan a partir de objetos de AD a través de ADWS. ESC6 (
EDITF_ATTRIBUTESUBJECTALTNAME2), ESC7 (ACLs de rol de CA) y ESC8 (inscripción web / relay NTLM) residen en el registro/endpoints HTTP del host de la CA y no son observables a través de ADWS —AD-CS-006marca que existe una CA para que puedan verificarse en el host (p. ej. con Certipy).
Requiere Go 1.26+. Sin otras dependencias de compilación.
# 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 debe ser el FQDN real del DC (no su IP): el encabezado SOAP To de ADWS se compara con el endpoint mediante el AddressFilter de WCF. Encuéntralo con, p. ej., 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