Obfuscation du PowerShell : s’infiltrer en profitant de la confusion, Partie I

PowerShell Obfuscation

Cet article fait partie de la série « Obfuscation du PowerShell ». Consultez les autres parties :

Pour vous mettre dans l’ambiance de ce billet, mieux vaut commencer par parcourir les premières diapos de cette présentation de Daniel Bohannon et Le Holmes, donnée à l’occasion de la conférence Black Hat 2017. Qui aurait cru qu’il faudrait avaler plus de cent diapos pour faire en sorte de rendre illisibles des commandes PowerShell ?

Nous savons que PowerShell est l’outil de post-exploitation incontournable, grâce auquel les hackers peuvent couler des jours heureux. Si vous avez besoin d’en avoir encore la preuve, lisez notre série d’articles sur les tests d’intrusion d’Active Directory.

Toutefois, l’équipe informatique surveille, en théorie, les activités des utilisateurs depuis le Centre de sécurité. On devrait donc facilement savoir quand une commande « anormale » est exécutée.

Voici un signe qu’une attaque PowerShell a lieu : un utilisateur crée un objet WebClient , appelle sa méthode Downloadstring puis exécute la chaîne contenue sur la page Web distante. En voici un exemple :

Pourquoi un utilisateur ordinaire, voire même un administrateur, ferait-il cela ?

Si ce « texte clair » est facile à détecter en examinant les journaux adéquats dans Windows et en recherchant les bons mots clés, la version obfusquée est tout sauf simple. À la fin de ce billet, nous verrons comment il est possible de faire en sorte que ce « pas de tir » basique utilisé par les hackers ait l’air d’un charabia complètement indéchiffrable.

Journalisation PowerShell

Avant de faire notre grand plongeon dans l’obfuscation, examinons comment les événements sont journalisés par Windows, en particulier pour PowerShell. Lorsque vous verrez les journaux, vous comprendrez mieux ce que les hackers tentent de dissimuler.

À sa décharge, Microsoft a pris conscience des vulnérabilités de PowerShell et a commencé à améliorer la journalisation des commandes dans Windows 7. Ces améliorations sont effectives dans PowerShell versions 4 et 5.

La version de Windows Server 2012 que j’ai utilisée dans mon environnement AWS est dotée de la version 4. Il semblerait que cette version possède la plupart des capacités avancées de journalisation, même si celles de la version 5 sont plus récentes et plus performantes.

D’après ce que j’ai réussi à capter en lisant la superbe présentation de Bohannon et auprès d’autres sources Microsoft, il faut activer l’événement 4688 (création de processus) puis activer la capacité d’audit pour la ligne de commande PowerShell. Vous en saurez plus en lisant ce document Microsoft.

Et, pour une journalisation encore plus touffue, vous pouvez définir des stratégies dans la console GPO, pour activer par exemple la journalisation complète de la transcription d’un PowerShell (ci-dessous).

D’autres fonctionnalités de journalisation PowerShell dans Administrate Template, sous Computer Configuration.

Non, je n’ai pas fait cela pour mon propre test ! J’ai découvert (comme beaucoup d’autres professionnels de la sécurité) que les choses ont tendance à devenir rapidement très confuses lorsque l’on utilise l’Observateur d’événements Windows. Je n’ai pas besoin de toute la puissance de la journalisation de la transcription.

Pour le fun, j’ai exécuté un pipeline simple Get-Process | %{Write-Host $_.Handles} pour imprimer les handles de processus, et j’ai généré ainsi… pas moins de 114 événements dans le journal PowerShell. Au passage, Ofer a publié un article intéressant dans lequel il explique le problème plus vaste de la mise en relation des différents événements pour comprendre la situation dans son ensemble.

Je l’ai ! Le pipeline à l’origine de la tonne d’événements liés.

La bonne nouvelle, c’est qu’à partir de l’Observateur d’événements, j’ai réussi à voir la ligne de commande de base qui a déclenché la cascade d’événements (voir ci-dessus).

Semer la confusion

L’objectif du hacker est de faire en sorte qu’il soit très difficile, voire impossible, pour le personnel de sécurité consultant le journal de détecter tout activité de piratage évidente ou, plus probablement, de tromper les logiciels d’analyse afin qu’ils n’émettent pas d’alerte lorsqu’un programme malveillant est chargé.

La présentation mentionnée précédemment contient un long exemple qui montre comment obfusquer une menace en exploitant la capacité de PowerShell à exécuter des commandes intégrées dans une chaîne.

Saviez-vous que ceci était possible ?

Ou, encore plus diabolique, ceci :

Ou, regardez ce que j’ai mitonné en utilisant ma propre recette :

Oui, PowerShell est incroyablement souple et les hackers savent y faire lorsqu’il s’agit de tirer avantage de ses fonctionnalités pour créer la confusion.

Vous pouvez aussi méditer sur cette tactique, qui utilise des variables d’environnement dans un bon vieux shell Windows pour dissimuler le code malveillant et l’insérer dans PowerShell :

Ne perdez pas de vue que dans un pipeline PowerShell, chaque portion exécute un processus séparé qui émet ses propres événements pour générer une confusion maximale dans le journal. Dans l’exemple ci-dessus, l’objectif est d’utiliser la variable %cmd% pour masquer le code malveillant.

Toutefois, depuis mon Observateur d’événements Windows, j’ai pu localiser la ligne de commande complète initiale — même si pour cela, j’ai dû fouiller pas mal.

En théorie, vous pouvez rechercher la signature réelle de la menace dans les journaux Windows, représentée dans mon exemple par « write-host evil malware », en examinant les lignes de commande.

Mais les hackers sont devenus très malins car ils rendent même la signature de la menace invisible. C’est l’exemple par lequel j’ai commencé.

L’idée est d’utiliser l’objet WebClient.Net pour lire la menace contenue sur un site distant et de l’exécuter avec la commande Invoke-Expression de PowerShell. Dans l’Observateur d’événements, le code réel n’est pas visible !

C’est ce que l’on appelle une menace sans fichier, une technique très utilisée par l’élite des hackers. Comme je l’ai dit en début de billet, les professionnels de la sécurité parent à cette astuce en cherchant plutôt WebClient et Downloadstring dans la ligne de commande. Il ne s’agit pas d’une commande utilisateur normale, du moins selon moi.

Coup-d’œil rapide sur Invoke-Obfuscation

C’est là qu’entre en jeu l’outil Invoke-Obfuscation de Bohannon. Pendant un an (sa barbe le prouve !), il a étudié toutes les techniques d’obfuscation de ligne de commande PowerShell utilisées pour rendre quasiment impossible l’analyse des mots clés évidents.

Ses obfuscations sont basées sur des séquences d’échappement et une programmation PowerShell intelligente pour manipuler les commandes.

J’ai chargé son appli Invoke-Expression sur mon serveur AWS et l’ai testée moi-même. Nous étudierons cet outil plus en détail dans le prochain billet, mais voici ce qui s’est passé lorsque j’ai inséré la chaîne de commande sans fichier Webclient.Downloadstring ci-dessus :

Obfuscation de chaîne à l’aide de l’appli Invoke-Obfuscation. Difficile de chercher des signatures de programmes malveillants dans tout ce fatras.

Quel embrouillamini ! Et j’ai pu tester le PowerShell obfusqué dans son appli.

La prochaine fois, nous examinerons de plus près de quoi est capable Invoke-Obfuscation et aborderons de nouvelles façons de localiser ces scripts PowerShell, embrouillés mais extrêmement dangereux.