
Ein praktischer Client für ADWS in Golang.
Ein praktischer Client für ADWS in Golang.
Sopa implementiert den ADWS-Protokollstack (MS-NNS + MC-NMF + SOAP) und stellt die folgenden Befehlszeilenfunktionen zur Verfügung:
query: führt LDAP-Filtersuchen über WS-Enumeration Enumerate + Pull-Schleife mit Attributprojektion, Bereichskontrolle (Base/OneLevel/Subtree) und Paginierung durchget: ruft ein einzelnes Objekt anhand des DN über WS-Transfer Get abcreate: erstellt Objekte über WS-Transfer ResourceFactory (eingebaute Typen: user, computer, group, OU, container; oder benutzerdefinierte Objekte aus einer YAML-Vorlage über IMDA AddRequest)delete: entfernt ein Objekt anhand des DN über WS-Transfer Deleteattr: fügt einzelne Attributwerte zu einem vorhandenen Objekt hinzu, ersetzt oder entfernt sie über WS-Transfer Put$ go install github.com/Macmod/sopa/cmd/sopa@latest
# Auth-Flags (-u, -p, -d, -k, -H, -c, ...) werden aus Gründen der Übersichtlichkeit weggelassen – siehe Abschnitt Authentifizierung.
# Objekte nach LDAP-Filter durchsuchen
$ sopa [auth_flags] query --dc <DC> --filter '(objectClass=*)'
# Ein einzelnes Objekt nach DN abrufen
$ sopa [auth_flags] get --dc <DC> --dn '<DN>'
# Ein Objekt nach DN löschen
$ sopa [auth_flags] delete --dc <DC> --dn '<DN>'
# Attributwerte bearbeiten
$ sopa [auth_flags] attr add --dc <DC> --dn '<DN>' --attr <ATTR> --value <VALUE>
$ sopa [auth_flags] attr replace --dc <DC> --dn '<DN>' --attr <ATTR> --value <VALUE>
$ sopa [auth_flags] attr delete --dc <DC> --dn '<DN>' --attr <ATTR>
# Objekte erstellen
$ sopa [auth_flags] create user --dc <DC> --name <CN> --pass <INITIAL_PASS>
$ sopa [auth_flags] create computer --dc <DC> --name <CN>
$ sopa [auth_flags] create group --dc <DC> --name <CN> --type GlobalSecurity
$ sopa [auth_flags] create ou --dc <DC> --name <CN>
$ sopa [auth_flags] create container --dc <DC> --name <CN>
$ sopa [auth_flags] create custom --dc <DC> --template <TEMPLATE.yaml>
# Kontokennwörter setzen / ändern (MS-ADCAP)
$ sopa [auth_flags] set-password --dc <DC> --dn '<DN>' --new <NEW_PASS>
$ sopa [auth_flags] change-password --dc <DC> --dn '<DN>' --old <OLD_PASS> --new <NEW_PASS>
# DN <-> kanonischen Namen übersetzen (MS-ADCAP)
# (dieser Aufruf ist größtenteils nutzlos, aber der Vollständigkeit halber beibehalten 😄)
$ sopa [auth_flags] translate-name --dc <DC> --offered DistinguishedName --desired CanonicalName '<DN>'
# Gruppenmitgliedschaften des Prinzipals (MS-ADCAP)
$ sopa [auth_flags] groups --dc <DC> --dn '<DN>' --membership --authz
# Gruppenmitglieder (MS-ADCAP)
$ sopa [auth_flags] members --dc <DC> --dn '<GROUP_DN>' --recursive
# Optionale AD-Funktion umschalten, z.B. Papierkorb (MS-ADCAP)
$ sopa [auth_flags] optfeature --dc <DC> --feature-id <FEATURE_GUID> --enable
# Topologie-Informationen (MS-ADCAP)
$ sopa [auth_flags] info version --dc <DC>
$ sopa [auth_flags] info domain --dc <DC>
$ sopa [auth_flags] info forest --dc <DC>
$ sopa [auth_flags] info dcs --dc <DC>
# ADWS-Dienstendpunkt-Metadaten (nicht authentifiziert – Auth-Flags nicht erforderlich)
$ sopa mex --dc <DC>
Führen Sie sopa ohne Unterbefehl aus, um eine interaktive Shell zu öffnen. Sie verwendet eine einzige Verbindung für alle Befehle und bietet Tab-Vervollständigung.
$ sopa --dc <DC> -u <USER> -p <PASS> -d <DOMAIN>
sopa v1.1.0
Connected dc.corp.local domain=corp.local user=Administrator
Type 'help' for commands or 'exit' to quit.
[corp.local]> query --filter '(objectClass=user)' --attrs sAMAccountName
[corp.local]> get --dn 'CN=Administrator,CN=Users,DC=corp,DC=local'
[corp.local]> exit
Verwenden Sie exit, quit oder Ctrl-D, um die Shell zu verlassen.
Beispielvorlage: examples/custom-create.example.yaml
Vorlagenschema (YAML):
parentDN (Zeichenkette, erforderlich): Container-DNrdn (Zeichenkette, erforderlich): Relativer DN für das neue Objekt (z.B. CN=Foo)attributes (Liste, erforderlich): jedes Element hat:
name (Zeichenkette, erforderlich): Attributname (cn oder addata:cn)type (Zeichenkette, optional): string|int|bool|base64|hex (oder explizit xsd:*), Standardwert stringvalue (Zeichenkette) oder values (Liste von Zeichenketten)Hinweise:
ad:relativeDistinguishedName oder ad:container-hierarchy-parent nicht in die Vorlage ein (sie werden automatisch eingefügt).hex-Werte werden in xsd:base64Binary konvertiert.value: "".--dc akzeptiert einen FQDN, eine IP-Adresse oder kann weggelassen werden.
Da der Hostname des DC manchmal nicht über das Standard-DNS des Netzwerks verfügbar ist, wird dringend empfohlen, immer --dns <DC-IP> zu verwenden, damit sopa für alle Lookups den eigenen DNS-Server des DC verwendet:
# Option 1: sopa alles über das DNS des DC auflösen lassen
$ sopa query --dns 192.168.1.10 -d corp.local -u user -p pass --filter '(objectClass=user)'
Wenn --dc weggelassen wird und --domain angegeben ist, entdeckt sopa automatisch einen DC durch Abfrage von SRV-Einträgen:
_ldap._tcp.<domain> (zuerst versucht)
_kerberos._tcp.<domain> (Fallback)
Das Ziel des Eintrags mit der höchsten Priorität wird verwendet. Dies erfordert, dass der mit --dns angegebene DNS-Server diese SRV-Abfragen beantworten kann – der eigene integrierte DNS-Server des DC (falls vorhanden) sollte dazu in der Lage sein.
# Option 2: DC explizit ohne Kerberos angeben
$ sopa info version --dc 192.168.1.10 --domain corp.local -u user -p pass
Wenn eine IP für --dc angegeben wird, wird die IP immer über eine reverse PTR-Abfrage in einen FQDN aufgelöst – der WCF-Adressfilter des ADWS-Endpunkts erfordert unabhängig von der Authentifizierungsmethode einen FQDN im wsa:To-Header.
Diese PTR-Abfrage erfolgt ebenfalls über --dns, daher ist eine korrekt konfigurierte Reverse-Zone auf dem DC erforderlich:
# Option 3: IP-Eingabe – PTR-Abfrage löst 192.168.1.10 -> dc.corp.local auf
$ sopa info version --dc 192.168.1.10 --dns 192.168.1.10 --domain corp.local -u user -p pass
Alle DNS-Operationen im Stack – DC-Erkennung, PTR-Auflösung, ADWS-TCP-Verbindungsaufbau und Kerberos-KDC-Verbindungen – verwenden denselben Resolver, der aus --dns / --dns-tcp aufgebaut wird.
sopa unterstützt die folgenden Anmeldeoptionen:
# Passwort
$ sopa --dc <DC> -d <DOMAIN> -u <USER> -p <PASS> <subcommand> [...]
# NT-Hash
$ sopa --dc <DC> -d <DOMAIN> -u <USER> -H <NT_HASH> <subcommand> [...]
# AES-Sitzungsschlüssel (Kerberos wird impliziert)
# 32 Hex-Zeichen = AES-128, 64 Hex-Zeichen = AES-256
$ sopa --dc <DC> -d <DOMAIN> -u <USER> --aes-key <HEX_KEY> <subcommand> [...]
# Kerberos-ccache (Kerberos wird impliziert)
$ sopa --dc <DC> -d <DOMAIN> -u <USER> -c <CCACHE_PATH> <subcommand> [...]
# PFX-Zertifikat (Kerberos wird impliziert / via PKINIT)
$ sopa --dc <DC> -d <DOMAIN> -u <USER> --pfx <CERT.pfx> --pfx-password <PFX_PASS> <subcommand> [...]
# PEM-Zertifikat (Kerberos wird impliziert / via PKINIT)
$ sopa --dc <DC> -d <DOMAIN> -u <USER> --cert <CERT.pem> --key <KEY.pem> <subcommand> [...]
Alle TCP-Verbindungen (ADWS, Kerberos, DNS) können über einen SOCKS5-Proxy mit -x / --socks5 getunnelt werden:
# Alles über einen SOCKS5-Proxy leiten
$ sopa -x 127.0.0.1:1080 --dc dc.corp.local -d corp.local -u user -p pass query --filter '(objectClass=user)'
# Das eigene DNS des DC über den Proxy verwenden, dann über den Proxy verbinden
$ sopa -x 127.0.0.1:1080 --dns 192.168.1.10 --dc 192.168.1.10 -d corp.local -u user -p pass query --filter '(objectClass=user)'
# DNS lokal behalten (z.B. DNS bereits ohne Proxy erreichbar), nur TCP-Verbindungen über den Proxy
$ sopa -x 127.0.0.1:1080 --no-proxy-dns --dc dc.corp.local -d corp.local -u user -p pass query --filter '(objectClass=user)'
Beiträge sind willkommen, indem Sie ein Issue eröffnen oder einen Pull-Request einreichen.
Die Idee, dieses Tool zu schreiben, entstand aus einer Welle von ADWS-fokussierten Tools, hauptsächlich zu Evasionszwecken. Theoretisch kann alles, was mit diesen Tools gemacht werden kann, auch mit sopa gemacht werden. Wenn Sie jedoch komplexere/spezifischere Aktionen durchführen möchten, sehen Sie sich auch diese an:
ssp-Paket den Authentifizierungsablauf mit GSSAPI nahtlos implementiert hat.Die MIT-Lizenz (MIT)
Copyright (c) 2023 Artur Henrique Marzano Gonzaga
Die Erlaubnis wird hiermit unentgeltlich jeder Person, die eine Kopie dieser Software und der zugehörigen Dokumentationsdateien (die "Software") erhält, erteilt, die Software ohne Einschränkung zu nutzen, einschließlich und ohne Einschränkung der Rechte zur Verwendung, Vervielfältigung, Änderung, Zusammenführung, Veröffentlichung, Verteilung, Unterlizenzierung und/oder zum Verkauf von Kopien der Software, und Personen, denen die Software zur Verfügung gestellt wird, dies unter den folgenden Bedingungen zu gestatten:
Der obige Urheberrechtshinweis und dieser Genehmigungshinweis sind in allen Kopien oder wesentlichen Teilen der Software zu enthalten.
DIE SOFTWARE WIRD IM "IST-ZUSTAND" ZUR VERFÜGUNG GESTELLT, OHNE IRGENDEINE AUSDRÜCKLICHE ODER STILLSCHWEIGENDE GEWÄHRLEISTUNG, EINSCHLIESSLICH, ABER NICHT BESCHRÄNKT AUF DIE GEWÄHRLEISTUNG DER MARKTGÄNGIGKEIT, DER EIGNUNG FÜR EINEN BESTIMMTEN ZWECK UND DER NICHTVERLETZUNG VON RECHTEN. IN KEINEM FALL SIND DIE AUTOREN ODER URHEBERRECHTSINHABER HAFTBAR FÜR JEGLICHE ANSPRÜCHE, SCHÄDEN ODER ANDERE VERPFLICHTUNGEN, OB AUS VERTRAG, UNERLAUBTER HANDLUNG ODER ANDERWEITIG, DIE SICH AUS ODER IN VERBINDUNG MIT DER SOFTWARE ODER DER NUTZUNG ODER ANDEREN GESCHÄFTEN MIT DER SOFTWARE ERGEBEN.
set-password: setzt ein Kontokennwort über MS-ADCAP SetPasswordchange-password: ändert ein Kontokennwort (erfordert das alte Kennwort) über MS-ADCAP ChangePasswordtranslate-name: konvertiert zwischen DN- und kanonischem Namensformat über TranslateNamegroups: listet Gruppenmitgliedschaften oder Autorisierungsgruppen eines Prinzipals über GetADPrincipalGroupMembership / GetADPrincipalAuthorizationGroup aufmembers: zählt Gruppenmitglieder auf (optional rekursiv) über GetADGroupMemberoptfeature: schaltet optionale AD-Funktionen um (z.B. Papierkorb) über ChangeOptionalFeatureinfo: ruft Topologie-Metadaten (Version, Domäne, Gesamtstruktur, DC-Liste) über GetVersion, GetADDomain, GetADForest, GetADDomainControllers abmex: ruft ADWS-Dienstendpunkt-Metadaten über eine nicht authentifizierte WS-MetadataExchange-Anfrage ab| Flagge | Beschreibung |
|---|
--dns <host[:port]> | Eigener DNS-Server für alle Lookups (SRV, PTR, forward). Standardmäßig Port 53. |
--dns-tcp | Erzwingt DNS-Abfragen über TCP statt UDP. Nützlich, wenn UDP blockiert ist oder SRV-Antworten groß sind. |
-x / --socks5 <host:port> | Leitet alle TCP-Verbindungen über einen SOCKS5-Proxy. DNS-Abfragen werden ebenfalls über den Proxy getunnelt, es sei denn, --no-proxy-dns ist gesetzt. |
--no-proxy-dns | Wenn --socks5 aktiv ist, wird DNS über den lokalen System-Resolver aufgelöst, anstatt über den Proxy. |
--dns-timeout <duration> | Timeout für DNS-Operationen (Standard 10s). |
--tcp-timeout <duration> | Timeout für TCP-Verbindungsaufbau und ADWS-Protokolloperationen (Standard 30s). |