Modification furtive d’un binaire de service pour l’élévation de privilèges et la persistance de l’accès

Wed 21 August 2019 by plissken

Contexte

Contexte : Test d’intrusion interne

Scénario : Malveillance interne (Scénario dit « du stagiaire malveillant »). Le stagiaire possède un compte utilisateur du domaine qui ne lui permet pas d’installer quoi que ce soit sur son poste. S’il souhaite attaquer d’autres machines sur le réseau, il lui faudra d’abord élever ses privilèges pour pouvoir installer des outils.

Objectif : Elever ses privilèges sur un poste de travail sur lequel est installé le master de l’entreprise.

Dans cet article, nous allons considérer que la recherche de vecteurs d’élévation de privilèges sur un poste Windows a révélé la présence d’un service avec les caractéristiques suivantes :

  • Le service se lance dans un contexte SYSTEM (niveau de privilèges le plus élevé sous Windows)
  • Le répertoire de l’exécutable lancé par le service est accessible en écriture pour tous les utilisateurs

La vulnérabilité se situe au niveau des permissions sur ce répertoire et les fichiers qu’il contient. En effet, ces dernières sont trop laxistes et permettent à un simple utilisateur du domaine de remplacer l’exécutable du service par un autre exécutable qui portera le même nom afin d’exécuter du code sur le poste avec des droits les plus élevés (contexte SYSTEM), après redémarrage du service. Ce redémarrage sera effectué en redémarrant le poste car les utilisateurs n’auront généralement pas le droit de redémarrer le service directement.

Dans un tel cas, il est tout à fait possible de remplacer l’exécutable par un autre dont le rôle est tout autre. Dans certaines situations telles qu’un pentest Red Team la furtivité est primordiale et nous oblige à prendre des précautions pour ne pas lever d’alertes. De ce fait, il est impératif que le service puisse toujours être en bon fonctionnement afin d’éviter les comportements suspects. Il va alors falloir modifier l’exécutable légitime pour ajouter des fonctionnalités supplémentaires qui ne perturberont pas celles d’origine.

Certains outils permettent de modifier des exécutables de service mais ils ne permettent pas toujours de conserver le bon fonctionnement du service. La solution sera alors de modifier manuellement l’exécutable pour garder le fonctionnement initial tout en ajoutant du code « malveillant ».

Informations utiles sur le service

Le service en question est utilisé pour le déploiement de package sur les postes. Son nom sera masqué pour des raisons de confidentialité.

L’exécutable a été développé avec un langage de programmation .Net. Cette information est importante car il s’agit d’un langage de programmation orienté objet qui utilise un compilateur avec machine virtuelle, multiplateforme et non natif. Le code généré n’est alors pas du code machine de type assembleur mais un code intermédiaire appelé Common Intermediate Language (CIL).

Par conséquent, il est possible de décompiler un programme, ce qui facilite la rétroconception et la modification de l’exécutable.

Décompilation du binaire de service

Le binaire a été décompilé avec l’outil ILSpy.

Décompilation avec ILSpy

La partie en haut à droite représente la méthode main() de la classe Program dans le langage C# et juste en dessous se trouve la même chose en langage intermédiaire (CIL) grâce au plugin Reflexil.

Toute modification du programme se fera au niveau du langage intermédiaire. Dans le cadre du pentest, il a été décidé de rajouter l’exécution d’une commande permettant la création du compte « Sogeti » et son ajout au groupe « Administrateurs ». Cela aura l’avantage de recréer un compte dans le groupe des administrateurs locaux au redémarrage du service si jamais le compte venait à être supprimé. On assure ainsi la persistance de l’accès.

Modification du binaire de service

Notre but va être de faire exécuter avant toute chose la commande :

net user /add sogeti  #S0g371#2018! & net localgroup Administrateurs sogeti /add

Il faut débuter la méthode main() par un appel à la méthode Process.Start à laquelle on fournira deux arguments :

  1. Le premier argument sera le nom du programme à exécuter et le second sera un jeu d’arguments de ligne de commande pour le programme à exécuter.

    Notre premier argument sera alors cmd (invite de commande).

  2. Le second argument sera /c net user /add sogeti  #S0g371#2018! & net localgroup Administrateurs sogeti /add (commande à exécuter via l’invite de commande).

Cependant, il ne faut pas oublier que la modification doit se faire au niveau du langage intermédiaire (CIL) avec le plugin Reflexil intégré dans ILSpy.

Ce plugin permet d’ajouter, supprimer ou modifier simplement des instructions dans la séquence existante.

Modification des instructions en langage intermédiaire avec Reflexil

Nous allons alors ajouter des instructions supplémentaires afin de faire exécuter notre commande au début de la méthode main(). Pour cela, nous avons besoin d’effectuer un call à la méthode Process.Start en ayant pris soin de pusher les arguments sur la pile avant.

Ainsi, nous allons commencer par pusher sur la pile le premier argument qui est la chaîne de caractère cmd en utilisant l’instruction ldstr. On utilise la même instruction pour pusher la deuxième chaîne sur la pile. Enfin, on termine avec l’instruction call sur la méthode Process.Start qui prendra alors comme arguments les 2 chaînes de caractères précédentes.

On obtient alors la séquence suivante :

Ajout de la séquence d'instructions

L’ajout de cette séquence d’instructions va entraîner la génération de code C# supplémentaire au début de la méthode main().

Ligne de code C# générée

Après cela, la dernière étape va consister à enregistrer les modifications pour obtenir notre nouveau binaire patché afin de le déposer dans le bon répertoire en lieu et place du binaire d’origine.

Un redémarrage du poste entraînera un redémarrage du service et par conséquent l’exécution de notre binaire qui fera exactement ce que le service est censé faire sauf qu’il aura pris soin de nous créer un compte dans le groupe des administrateurs locaux.

Code exécuté avec succès

Conclusion

Cette méthode furtive de modification d’un binaire de service présente l’avantage d’être facilement réalisable (le plugin Reflexil intégré dans ILSpy est très simple d’utilisation) et garantit la persistance du compte ou de toute autre modification effectuée si on choisit d’exécuter d’autres commandes.