
Un client pratico per ADWS in Golang.
Un client pratico per ADWS in Golang.
Sopa implementa lo stack di protocollo ADWS (MS-NNS + MC-NMF + SOAP), esponendo le seguenti funzionalità da riga di comando:
query: esegue ricerche con filtro LDAP tramite il loop WS-Enumeration Enumerate + Pull con proiezione di attributi, controllo dello scope (Base/OneLevel/Subtree) e paginazioneget: recupera un singolo oggetto per DN tramite WS-Transfer Getcreate: crea oggetti tramite WS-Transfer ResourceFactory (tipi incorporati: user, computer, group, OU, container; oppure oggetti personalizzati da un template YAML tramite IMDA AddRequest)delete: rimuove un oggetto per DN tramite WS-Transfer Deleteattr: aggiunge, sostituisce o rimuove singoli valori di attributo su un oggetto esistente tramite WS-Transfer Put$ go install github.com/Macmod/sopa/cmd/sopa@latest
# I flag di autenticazione (-u, -p, -d, -k, -H, -c, ...) sono omessi per brevità - vedere la sezione Autenticazione.
# Cerca oggetti per filtro LDAP
$ sopa [auth_flags] query --dc <DC> --filter '(objectClass=*)'
# Recupera un singolo oggetto per DN
$ sopa [auth_flags] get --dc <DC> --dn '<DN>'
# Elimina un oggetto per DN
$ sopa [auth_flags] delete --dc <DC> --dn '<DN>'
# Modifica valori degli attributi
$ 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>
# Crea oggetti
$ 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>
# Imposta / cambia password dell'account (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>
# Traduci DN <-> nome canonico (MS-ADCAP)
# (questa chiamata è per lo più inutile ma mantenuta per completezza 😄)
$ sopa [auth_flags] translate-name --dc <DC> --offered DistinguishedName --desired CanonicalName '<DN>'
# Appartenenze ai gruppi del principal (MS-ADCAP)
$ sopa [auth_flags] groups --dc <DC> --dn '<DN>' --membership --authz
# Membri del gruppo (MS-ADCAP)
$ sopa [auth_flags] members --dc <DC> --dn '<GROUP_DN>' --recursive
# Attiva/disattiva funzionalità AD opzionale, es. Cestino (MS-ADCAP)
$ sopa [auth_flags] optfeature --dc <DC> --feature-id <FEATURE_GUID> --enable
# Informazioni sulla topologia (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>
# Metadati dell'endpoint del servizio ADWS (non autenticato - i flag di autenticazione non sono necessari)
$ sopa mex --dc <DC>
Esegui sopa senza un sottocomando per aprire una shell interattiva. Riutilizza una singola connessione per tutti i comandi e fornisce completamento tramite tab.
$ sopa --dc <DC> -u <USER> -p <PASS> -d <DOMAIN>
sopa v1.1.0
Connesso a dc.corp.local domain=corp.local user=Administrator
Digita 'help' per i comandi o 'exit' per uscire.
[corp.local]> query --filter '(objectClass=user)' --attrs sAMAccountName
[corp.local]> get --dn 'CN=Administrator,CN=Users,DC=corp,DC=local'
[corp.local]> exit
Usa exit, quit o Ctrl-D per uscire dalla shell.
Esempio di template: examples/custom-create.example.yaml
Schema del template (YAML):
parentDN (stringa, obbligatorio): DN del contenitorerdn (stringa, obbligatorio): DN relativo per il nuovo oggetto (es. CN=Foo)attributes (lista, obbligatorio): ogni elemento ha:
name (stringa, obbligatorio): nome dell'attributo (cn o addata:cn)type (stringa, opzionale): string|int|bool|base64|hex (oppure esplicito xsd:*), predefinito stringvalue (stringa) o values (lista di stringhe)Note:
ad:relativeDistinguishedName o ad:container-hierarchy-parent nel template (vengono inseriti automaticamente).hex vengono convertiti in xsd:base64Binary.value: "".--dc accetta un FQDN, un indirizzo IP, o può essere omesso.
Poiché il nome host del DC a volte non è disponibile dal DNS predefinito della rete, si consiglia vivamente di passare sempre --dns <DC-IP> in modo che sopa utilizzi il proprio server DNS del DC per tutte le ricerche:
# Opzione 1: lascia che sopa risolva tutto tramite il DNS del DC
$ sopa query --dns 192.168.1.10 -d corp.local -u user -p pass --filter '(objectClass=user)'
Quando --dc viene omesso e --domain viene fornito, sopa scopre automaticamente un DC
interrogando i record SRV:
_ldap._tcp.<domain> (provato per primo)
_kerberos._tcp.<domain> (fallback)
Viene utilizzato il target del record con priorità più alta. Ciò richiede che il
server DNS indicato da --dns possa rispondere a quelle query SRV - il server DNS
integrato del DC (quando presente) dovrebbe essere in grado di farlo.
# Opzione 2: specifica il DC esplicitamente senza Kerberos
$ sopa info version --dc 192.168.1.10 --domain corp.local -u user -p pass
Quando viene fornito un IP per --dc, l'IP viene sempre risolto in un FQDN tramite una ricerca PTR inversa - il filtro dell'indirizzo WCF dell'endpoint ADWS richiede un FQDN nell'intestazione wsa:To indipendentemente dal metodo di autenticazione.
Anche questa ricerca PTR passa attraverso --dns, quindi è necessaria una zona
inversa correttamente configurata sul DC:
# Opzione 3: input IP - la ricerca PTR risolve 192.168.1.10 -> dc.corp.local
$ sopa info version --dc 192.168.1.10 --dns 192.168.1.10 --domain corp.local -u user -p pass
Tutte le operazioni DNS nello stack - scoperta DC, risoluzione PTR, dial TCP ADWS,
e connessioni KDC Kerberos - utilizzano lo stesso resolver costruito da --dns /
--dns-tcp.
sopa supporta le seguenti modalità di credenziali:
# Password
$ sopa --dc <DC> -d <DOMAIN> -u <USER> -p <PASS> <subcommand> [...]
# Hash NT
$ sopa --dc <DC> -d <DOMAIN> -u <USER> -H <NT_HASH> <subcommand> [...]
# Chiave di sessione AES (Kerberos è implicito)
# 32 caratteri esadecimali = AES-128, 64 caratteri esadecimali = AES-256
$ sopa --dc <DC> -d <DOMAIN> -u <USER> --aes-key <HEX_KEY> <subcommand> [...]
# Kerberos ccache (Kerberos è implicito)
$ sopa --dc <DC> -d <DOMAIN> -u <USER> -c <CCACHE_PATH> <subcommand> [...]
# Certificato PFX (Kerberos è implicito / tramite PKINIT)
$ sopa --dc <DC> -d <DOMAIN> -u <USER> --pfx <CERT.pfx> --pfx-password <PFX_PASS> <subcommand> [...]
# Certificato PEM (Kerberos è implicito / tramite PKINIT)
$ sopa --dc <DC> -d <DOMAIN> -u <USER> --cert <CERT.pem> --key <KEY.pem> <subcommand> [...]
Tutte le connessioni TCP (ADWS, Kerberos, DNS) possono essere tunnellate attraverso un proxy SOCKS5 tramite -x / --socks5:
# Instrada tutto attraverso un proxy SOCKS5
$ sopa -x 127.0.0.1:1080 --dc dc.corp.local -d corp.local -u user -p pass query --filter '(objectClass=user)'
# Usa il DNS del DC attraverso il proxy, poi connetti tramite proxy
$ 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)'
# Mantieni il DNS locale (es. DNS già raggiungibile senza proxy), solo connessioni TCP tramite 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)'
I contributi sono benvenuti aprendo un issue o inviando una pull request.
L'idea di scrivere questo strumento è nata da un'ondata di strumenti incentrati su ADWS, principalmente per scopi di evasione. In teoria tutto ciò che si può fare con questi si può fare anche con sopa, ma se vuoi eseguire azioni più complesse/specifiche, dai un'occhiata anche a loro:
ssp ha implementato il flusso di autenticazione con GSSAPI in modo impeccabile.La licenza MIT (MIT)
Copyright (c) 2023 Artur Henrique Marzano Gonzaga
Con la presente viene concessa l'autorizzazione, a titolo gratuito, a chiunque ottenga una copia di questo software e dei file di documentazione associati (il "Software"), di utilizzare il Software senza restrizioni, inclusi, a titolo esemplificativo ma non esaustivo, i diritti di utilizzare, copiare, modificare, unire, pubblicare, distribuire, concedere in sublicenza e/o vendere copie del Software, e di consentire alle persone a cui il Software è fornito di fare altrettanto, alle seguenti condizioni:
Il suddetto avviso di copyright e questa nota di autorizzazione devono essere inclusi in tutte le copie o parti sostanziali del Software.
IL SOFTWARE VIENE FORNITO "COSÌ COM'È", SENZA GARANZIA DI ALCUN TIPO, ESPRESSA O IMPLICITA, IVI INCLUSE, A TITOLO ESEMPLIFICATIVO MA NON ESAUSTIVO, LE GARANZIE DI COMMERCIABILITÀ, IDONEITÀ A UNO SCOPO PARTICOLARE E NON VIOLAZIONE. IN NESSUN CASO GLI AUTORI O I TITOLARI DEL COPYRIGHT POTRANNO ESSERE RITENUTI RESPONSABILI PER QUALSIASI RECLAMO, DANNO O ALTRA RESPONSABILITÀ, SIA IN UN'AZIONE CONTRATTUALE, EXTRACONTRATTUALE O ALTRO, DERIVANTE DA, O IN CONNESSIONE CON, IL SOFTWARE O L'USO O ALTRE OPERAZIONI NEL SOFTWARE.
set-password: imposta una password dell'account tramite MS-ADCAP SetPasswordchange-password: cambia una password dell'account (richiede la vecchia password) tramite MS-ADCAP ChangePasswordtranslate-name: converte tra formati DN e nome canonico tramite TranslateNamegroups: elenca le appartenenze ai gruppi o i gruppi di autorizzazione di un principal tramite GetADPrincipalGroupMembership / GetADPrincipalAuthorizationGroupmembers: enumera i membri del gruppo (opzionalmente ricorsivi) tramite GetADGroupMemberoptfeature: attiva/disattiva le funzionalità AD opzionali (es. Cestino) tramite ChangeOptionalFeatureinfo: recupera metadati di topologia (versione, dominio, foresta, elenco DC) tramite GetVersion, GetADDomain, GetADForest, GetADDomainControllersmex: recupera metadati dell'endpoint del servizio ADWS tramite una richiesta WS-MetadataExchange non autenticata| Flag | Descrizione |
|---|
--dns <host[:port]> | Server DNS personalizzato per tutte le ricerche (SRV, PTR, forward). Predefinito porta 53. |
--dns-tcp | Forza le query DNS su TCP invece che UDP. Utile quando UDP è bloccato o le risposte SRV sono grandi. |
-x / --socks5 <host:port> | Instrada tutte le connessioni TCP attraverso un proxy SOCKS5. Anche le query DNS vengono tunnellate attraverso il proxy a meno che non sia impostato --no-proxy-dns. |
--no-proxy-dns | Quando --socks5 è attivo, risolve il DNS tramite il resolver di sistema locale invece del proxy. |
--dns-timeout <duration> | Timeout per le operazioni DNS (default 10s). |
--tcp-timeout <duration> | Timeout per il dial TCP e le operazioni del protocollo ADWS (default 30s). |