Injection de DLL dans le service IKEEXT : un moyen (encore) efficace pour élever ses privilèges sous Windows – Partie 1/2

Sur les systèmes Windows, l’injection de DLL dans le service IKEEXT est un sujet qui remonte à la fin de l’année 2012. Il s’agit d’une faiblesse donnant lieu à une élévation de privilèges sous certaines conditions. Introduit sous Vista, ce problème n’a cependant été corrigé qu’à partir de Windows 8.1. Or, les systèmes Windows 7/Server 2008 R2 sont, encore aujourd’hui, largement présents dans les entreprises et force est de constater que son exploitation est toujours aussi simple et efficace.

1. Problématique

Lorsqu’il s’agit d’élever ses privilèges sous Windows, une technique classique consiste à injecter une bibliothèque dynamique (ou DLL) dans un programme s’exécutant avec des droits plus élevés. En théorie, il faut donc qu’un logiciel tiers soit installé sur la machine et qu’il soit vulnérable à ce type d’attaque.

C’est ici que le service IKEEXT intervient. Ce dernier est nativement intégré au système d’exploitation de Microsoft (à partir de NT 6.0) et implémente les protocoles IKE (Internet Key Exchange) et AuthIP (Authenticated internet Protocol). Il assure ainsi l’établissement de sessions VPN au moyen de tunnels IPSec (Internet Protocol Security).

Dans le cadre de cet article, les caractéristiques suivantes nous intéresseront tout particulièrement.

  • il est exécuté en tant qu’« AUTORITE NT\Système » ;
  • il tente de charger une DLL non présente par défaut ;
  • le chemin de recherche de cette DLL n’est pas défini et elle est chargée par son nom uniquement.

Afin de bien comprendre la nature de cette faiblesse du service IKEEXT, il est nécessaire de faire un rappel sur un élément clé du fonctionnement de Windows : le processus de recherche des DLL sur le système.

Si la DLL est chargée simplement par son nom dans le code source de l’application et que le mode SafeDllSearchMode est activé (clé de registre), le système la cherchera dans les répertoires suivants et selon cet ordre [1] :

  1. le dossier depuis lequel l’application est lancée ;
  2. le dossier système (C:\Windows\System32\ par défaut) ;
  3. le dossier système 16 bits (C:\Windows\System\ par défaut) ;
  4. le dossier Windows (C:\Windows\ par défaut) ;
  5. le dossier courant ;
  6. les dossiers listés dans la variable d’environnement PATH (environnement SYSTEM).

Si le mode SafeDllSearchMode est désactivé, l’ordre de recherche des DLL est légèrement différent, mais ne change rien dans le cadre du sujet traité ici. En effet, seul l’ordre des dossiers système est modifié et les chemins renseignés dans le PATH seront quant à eux toujours traités en dernier.

Cela signifie que si nous créons une DLL « malicieuse » et que nous parvenons à la placer dans un de ces répertoires, elle sera alors chargée et exécutée par notre fameux service IKEEXT, dans le contexte de l’utilisateur « AUTORITE NT\Système ». Les cinq premiers répertoires présentent peu d’intérêt, car non accessibles en écriture par défaut à un utilisateur standard. En revanche, la variable d’environnement « PATH » est quant à elle susceptible d’évoluer et pourrait éventuellement contenir un chemin vers un dossier dont nous contrôlons le contenu.

2. Contexte

Les versions suivantes de Windows [2] sont vulnérables :

Version Poste de travail Serveur
NT6.0 Windows Vista Windows Server 2008
NT6.1 Windows 7 Windows Server 2008 R2
NT6.2 Windows 8 Windows Server 2012

Cette vulnérabilité a été découverte il y a maintenant plus de 4 ans par le « High-Tech Bridge Security Research Lab » [3]. Plusieurs CVE ont alors été référencées :

  • CVE-2012-5377 : ActivePerl 5.16.1.1601 ;
  • CVE-2012-5378 : Active Tcl 8.5.12 ;
  • CVE-2012-5379 : Active Python 3.2.2.3 ;
  • CVE-2012-5380 : Ruby 1.9.3-p194 ;
  • CVE-2012-5381 : PHP 5.3.17 ;
  • CVE-2012-5382 : Zend Server 5.6.0 SP4 ;
  • CVE-2012-5383 : Oracle MySQL 5.5.28.

Suite à cette découverte, la position de Microsoft a été de dire que la vulnérabilité n’était pas inhérente au système d’exploitation, mais était plutôt introduite lors de l’installation de certains logiciels tiers. Ce qui, dans les faits, n’est pas incorrect. Dès lors, aucune CVE concernant les produits de Microsoft n’a été publiée. En revanche, chaque application permettant d’exploiter cette faiblesse devrait théoriquement faire l’objet d’un identifiant unique. On comprendra alors que la liste établie plus haut ne peut être exhaustive.

Et pour cause ! Ce cas se présente quasiment à chaque fois qu’un logiciel s’installe à la racine de la partition système C:\. En effet, à cet endroit, les répertoires nouvellement créés sont automatiquement accessibles en écriture à tous les utilisateurs authentifiés, contrairement à C:\Program Files\ par exemple, où les droits des nouveaux dossiers sont hérités.

L’ampleur et le potentiel de cette faille sont d’autant plus élevés que la présence des systèmes listés dans le tableau précédent est grande. À titre d’exemple, Windows Server 2008 (R2) bénéficie encore d’une utilisation massive, avec une part de marché évaluée à 45% dans le monde au début du second semestre 2016 [4]. Par ailleurs, le passage à Windows 10 est souvent considéré avec frilosité par les administrateurs système. Ainsi, encore aujourd’hui, la probabilité de présence de cette vulnérabilité reste non négligeable. C’est d’ailleurs ce que constatent souvent les ingénieurs de NES lors de tests effectués sur des postes de travail ou en environnements virtualisés par exemple.

Afin d’illustrer ce qui va suivre, nous avons choisi d’utiliser une machine virtuelle sur laquelle est installé le système d’exploitation Windows 7 Pro. Par ailleurs, il est important de noter que le système n’est pas vulnérable dans sa configuration par défaut. L’outil Python 2.7.12 sera donc installé en activant l’option ajoutant le chemin d’installation de Python dans la variable PATH. Deux comptes seront créés : un administrateur « NesAdmin » et un utilisateur standard « Nes ».

3. Détection de la vulnérabilité

Tout d’abord, il est nécessaire d’analyser les actions effectuées par le service IKEEXT lors de son démarrage. Pour cela, l’outil « Process Monitor » de la suite « Sysinternals » [5] a été utilisé. Après avoir lancé manuellement le service, nous obtenons le résultat suivant :

Fig. 1 : Analyse du chargement des DLL par le service IKEEXT.

Nous observons que le service IKEEXT tente de charger une bibliothèque dynamique nommée wlbsctrl.dll. Comme expliqué en introduction, le système la recherche d’abord dans ses dossiers puis il consulte finalement tous ceux listés dans la variable d’environnement « PATH » s’il ne l’a pas trouvée avant. Nous noterons en particulier la présence des chemins C:\Python27\ et C:\Python27\Scripts\.

L’étape suivante consiste à vérifier si au moins l’un de ces dossiers est accessible en écriture à notre utilisateur standard « Nes ». Pour cela, il suffit de tenter de créer un simple fichier texte vide dans l’un de ces répertoires. Dans notre cas, cette action est par exemple possible dans C:\Python27\Scripts. À partir de là, nous savons que le système est vulnérable.

Afin d’automatiser ce processus de détection et de recueillir d’autres informations sur le système, un script PowerShell a été spécialement développé. Voyons ce qu’il nous indique dans le cas de notre machine :

L’outil parvient à la même conclusion : la machine est bel et bien vulnérable.

4. Exploitation

Nous entrons à présent dans la phase la plus intéressante : l’exploitation. Celle-ci se déroulera en trois étapes.

  1. Créer une DLL malicieuse.
  2. Copier la DLL dans le dossier C:\Python27\Scripts\.
  3. Redémarrer le service IKEEXT.

Les choix effectués lors de la conception de la DLL dépendent fortement du scénario d’exploitation et du contexte dans lequel on se trouve. Certains choisiront par exemple d’y intégrer un « reverse shell » (notamment grâce à l’outil msfvenom de la suite Metasploit). Ici, nous avons préféré implémenter un code qui soit le plus flexible possible afin de s’adapter à chaque situation sans avoir à recompiler les sources.

Pour ce faire, la charge réelle du code d’exploitation sera déportée dans un script BATCH que l’on nommera arbitrairement payload.bat. Le code de la DLL devra alors réaliser les opérations suivantes :

  1. Obtenir de manière dynamique le chemin absolu du répertoire depuis lequel elle a été chargée. La méthode GetModuleFileNameW répond parfaitement à cette problématique.
  2. Construire la ligne de commandes cmd.exe /c C:\CHEMIN\VERS\payload.bat.
  3. Créer un nouveau processus à partir du résultat obtenu, grâce à la méthode « CreateProcess ».

Une fois le code implémenté, deux points d’attention doivent être vérifiés avant de compiler :

  • L’architecture-cible doit être respectée : 32 bits ou 64 bits.
  • Le projet doit être compilé de manière statique afin d’assurer la portabilité du code.

Une fois cette étape-clé réalisée, la suite est relativement simple, il faut renommer le fichier DLL ( wlbsctrl.dll) puis le déposer dans l’un des dossiers repérés précédemment. Ici, nous avons choisi le répertoire C:\Python27\Scripts\. Un fichier payload.bat est également créé au même endroit. Ce script BATCH contiendra les commandes nécessaires à la création d’un compte administrateur local que l’on nommera « NesHacker ».

La dernière étape consiste à redémarrer le service IKEEXT. Il essaiera alors à nouveau de charger la bibliothèque dynamique wlbsctrl.dll, mais, cette fois-ci, il trouvera celle que nous avons créée, dans le dossier C:\Python27\Scripts\. Le problème est que ce service ne peut être démarré ou arrêté que par un administrateur. En tant qu’utilisateur standard, la seule solution est donc de redémarrer complètement la machine.

Afin de valider de manière visuelle le fonctionnement du code d’exploitation, nous avons cependant choisi de redémarrer manuellement le service en utilisant le compte « NesAdmin ». Grâce à cette méthode, il est possible d’exécuter « Process Monitor » en parallèle pour analyser son comportement lors de son démarrage.

Cette nouvelle analyse montre que le service parvient à charger notre DLL depuis le répertoire C:\Python27\Scripts\. Un nouveau processus cmd.exe exécutant C:\Python27\Scripts\payload.bat est alors créé.

Finalement, de retour dans la session de l’utilisateur standard, nous pouvons vérifier que l’utilisateur « NesHacker » a effectivement été ajouté et qu’il est présent dans le groupe des administrateurs locaux, preuve que l’attaque a fonctionné.

L’attaquant dispose désormais d’un compte Administrateur local et contrôle donc complètement la machine.

Clément LABRO
Ingénieur sécurité chez NES

La seconde partie de cet article sera publiée prochainement sur le blog, restez connectés 😉

Retrouvez cet article (et bien d’autres) dans MISC n°90, disponible sur la boutique et sur la plateforme de lecture en ligne Connect !

Laisser un commentaire