Mouvement latéral sans fichier avec des objets COM piégés

Gros plan sur les mains d'un homme tapant sur un ordinateur portable et tenant une tablette dans un bureau sombre et éclairé en bleu.

Le modèle d'objet composant (COM) est une pierre angulaire du développement de Microsoft Windows depuis le début des années 1990 et il est encore très répandu dans les systèmes d'exploitation et applications Windows modernes. L'utilisation de composants COM et le développement de nombreuses fonctionnalités au fil des ans ont créé une surface d'attaque généreuse. En février 2025, James Forshaw (@tiraniddo) de Google Project Zero a publié un article de blog détaillant une nouvelle approche pour abuser de la technologie de transfert COM, Distributed COM (DCOM), où des objets COM piégés peuvent être utilisés pour exécuter du code géré.NET dans le contexte d’un serveur processus DCOM . M. Forshaw met en évidence plusieurs cas d'utilisation pour l'escalade des privilèges et le contournement de Protected Process Light (PPL).

Sur la base des recherches de Forshaw, Mohamed Fakroud (@T3nb3w) a publié une implémentation de la technique pour contourner les protections PPL début mars 2025. Jimmy Bayne (@bohops) et moi avons mené des recherches similaires en février 2025, ce qui nous a conduits à développer une technique de mouvement latéral sans fichier en abusant d’objets COM piégés.

Contexte

COM est une norme d’interface binaire et un niveau de service middleware qui permet d’exposer des composants distincts et modulaires pour interagir entre eux et avec les applications, quel que soit le langage de programmation sous-jacent. Par exemple, les objets COM développés en C++ peuvent facilement s'interfacer avec une application .NET, ce qui permet aux développeurs d'intégrer efficacement divers modules logiciels. DCOM est une technologie à distance qui permet aux clients COM de communiquer avec les serveurs COM via la communication inter-processus (IPC) ou des appels de procédure à distance (RPC). De nombreux services Windows implémentent des composants DCOM accessibles localement ou à distance.

Les classes COM sont généralement enregistrées et contenues dans le registre Windows. Un programme client interagit avec un serveur COM en créant une instance de la classe COM, appelée objet COM. Cet objet fournit un pointeur vers une interface standardisée. Le client utilise ce pointeur pour accéder aux méthodes et aux propriétés de l’objet, facilitant ainsi la communication et les fonctionnalités entre le client et le serveur.

Les objets COM sont souvent des cibles de recherche pour évaluer l'exposition aux vulnérabilités et découvrir des fonctionnalités abusables. Un objet COM piégé est une classe de bug dans laquelle un client COM instancie une classe COM dans un serveur DCOM hors processus, où le client contrôle l’objet COM via un pointeur d’objet marshalé par référence. Selon la condition, ce vecteur de contrôle peut présenter des failles logiques liées à la sécurité.

Le blog de Forshaw décrit un cas d’utilisation de contournement PPL où l’interface IDispatch , telle qu’exposée dans la classe COM WaaSRemediation , est manipulée pour l’abus d’objets COM piégés et l’exécution de code .NET. WaaSRemediation est implémenté dans le service WaaSMedicSvc, qui s'exécute en tant que processus protégé svchost.exe dans le contexte de NT AUTHORITY\SYSTEM. L’excellente présentation de Forshaw a servi de base à nos recherches appliquées et au développement d’une technique de mouvement latéral sans fichier de preuve de concept.

Homme regardant un ordinateur

Renforcez vos renseignements de sécurité 


Gardez une longueur d’avance sur les menaces grâce à l’actualité et aux réflexions sur la sécurité, l’IA et bien plus encore, dans la newsletter hebdomadaire Think. 


Aperçu de la recherche

Notre parcours de recherche a commencé par la découverte de la classe COM WaaSRemediation qui prend en charge l’interface IDispatch . Cette interface permet aux clients d’effectuer une liaison tardive. Normalement, les clients COM ont défini l’interface et les définitions de type des objets qu’ils utilisent au moment de la compilation. Au contraire, la liaison tardive permet au client de découvrir et d’appeler des méthodes sur l’objet au moment de l’exécution. IDispatch comprend la méthode GetTypeInfo , qui renvoie une interface ITypeInfo. ITypeInfo possède des méthodes qui peuvent être utilisées pour découvrir des informations sur le type de l’objet qui l’implémente.

Si une classe COM utilise une bibliothèque de types, elle peut être interrogée par le client via ITypeLib (obtenue à partir de ITypeInfo-> GetContainingTypeLib) pour récupérer des informations de type. De plus, les bibliothèques de types peuvent également référencer d’autres bibliothèques de types pour obtenir des informations supplémentaires sur les types.

Selon l’article de blog de Forshaw, WaaSRemediation fait référence à la bibliothèque de types WaaSRemediationLib, qui à son tour fait référence à stdole (automatisation). WaaSRemediationLib utilise deux classes COM de cette bibliothèque, StdFont et StdPicture. En effectuant COM Hijacking sur l’objet StdFont via la modification de sa clé TreatAs de registre, la classe pointera vers une autre classe COM de notre choix, telle que System.Object dans le cadre des exigences .NET. Forshaw souligne que StdPicture n’est pas viable, car cet objet effectue une vérification de l’instanciation hors processus.

Les objets .NET nous intéressent grâce à la méthode GetTypede System.Object . Grâce à GetType, nous pouvons effectuer une réflexion .NET pour accéder finalement à Assembly.Load. Bien que System.Object ait été choisi, ce type est la racine de la hiérarchie de types dans .NET. Par conséquent, n’importe quel objet COM .NET peut être utilisé.

Une fois l’étape initiale franchie, deux autres valeurs DWORD sous la clé HKLM\Software\Microsoft\.NetFramework étaient nécessaires pour faire de notre cas d’utilisation perçu une réalité :

  • AllowDCOMReflection : Comme l’a noté Forshaw, cette valeur activée nous permet d’effectuer une réflexion arbitraire pour appeler n’importe quelle méthode .NET. En règle générale, la réflexion.NET sur DCOM est impossible en raison des mesures d’atténuation traitées dans le document MS14-009.
  • OnlyUseLatestCLR : Avec Procmon, nous avons découvert que cette valeur doit être activée pour charger la dernière version du .NET CLR (version 4), sinon la version 2 est chargée par défaut.

Après avoir confirmé que la dernière version du CLR et de .NET pouvait être chargée lors de nos premiers tests, nous avons su que nous étions sur la bonne voie.

Du processus local à l’ordinateur distant

Afin de nous concentrer sur les aspects programmatiques à distance, nous avons d’abord utilisé le registre à distance. les valeurs clés du registreNetFramework et détournent l'objet StdFont sur la machine cible. Ensuite, nous avons remplacé CoCreateInstance par CoCreateInstanceEx pour instancier l'objet COM WaaSRemediation sur la cible distante et obtenir un pointeur sur l'interface IDispatch .

Avec un pointeur sur IDispatch, nous appelons la méthode membre GetTypeInfo pour obtenir un pointeur sur l'interface ITypeInfo, qui est piégée dans le serveur. Les méthodes membres appelées ensuite se produisent côté serveur. Après avoir identifié la référence de bibliothèque de type contenue d'intérêt(stdole) et dérivé la référence d'objet de classe subséquente d'intérêt(StdFont), nous avons finalement utilisé la méthode " remotable " CreateInstance de l'interface ITypeInfo pour rediriger le flux de lien d'objet StdFont (via la manipulation préalable de TreatAs ) afin d'instancier System.Object.

Comme AllowDCOMReflection est correctement défini, nous pouvons alors effectuer une réflexion .NET sur DCOM pour accéder à Assembly.Load afin de charger un assemblage .NET dans le serveur COM. Puisque nous utilisons Assembly.Load via DCOM, cette technique de mouvement latéral est complètement dépourvue de fichiers car le transfert d'octets de l'assemblage est géré par la magie de remoting de DCOM. Pour une explication approfondie de ce flux technique, de l’instanciation d’objets à la réflexion, veuillez vous référer au diagramme suivant :

organigramme montrant l'instanciation de la classe System.Object
Flux d'instanciation de la classe System.Object

Difficultés de développement

Notre premier et principal problème était d'appeler Assembly.Load_3, via IDispatch->Invoke. Invoke transmet un tableau d'objets à la fonction cible, et Load_3 est la surcharge de Assembly.Load qui prend un tableau d'un seul octet. Nous devions donc encapsuler le SafeARRAY d’octets dans un autre SafeARRAY de Variants . Au départ, nous avons continué à essayer de faire passer un seul SafeARRAY d’octets.

Code montrant comment créer un équivalent non géré de Object Byte
Créer un équivalent non géré de l’octet objet

Un autre problème consistait à trouver la surcharge Assembly.Load appropriée. Les fonctions d’assistance étaient tirées du code CVE-2014-0257 de Forshaw, qui incluait la fonction GetStaticMethod . Cette fonction utilisait la réflexion .NET sur DCOM pour trouver une méthode statique à partir d’un pointeur de type, du nom de la méthode et de son nombre de paramètres. Assembly.Load possède deux surcharges statiques qui nécessitent un seul argument ; nous avons donc fini par utiliser une solution bidon. Nous avons constaté que la troisième instance de Load avec un seul argument était le bon choix.

code utilisé pour rechercher la surcharge Assembly.Load appropriée
Recherche de l’assemblage.Load approprié

Douleurs opérationnelles

L'un des principaux inconvénients que nous avons observés avec cette technique était que la durée de vie de la balise générée était limitée au client COM ; en l'occurrence, la durée de vie de l'application de notre binaire d'armement « ForsHops.exe » (nom élégant, bien sûr). Donc, si ForsHops.exe nettoyait ses références COM ou sortait, il en irait de même pour la balise qui s'exécutait sous le fichier svchost.exe de la machine distante. Nous avons essayé différentes solutions, comme faire en sorte que notre assembleur .NET suspende indéfiniment son thread principal, exécute du shellcode dans un autre thread et laisse ForsHops.exe laisser l'exploit en suspens, mais rien n’était élégant.

Le thread principal de .NET Loader se bloque alors que le shellcode s'exécute dans un thread séparé
Le thread principal de .NET Loader se bloque alors que le shellcode s'exécute dans un thread séparé

Dans son état actuel, ForsHops.exe s'exécute jusqu'à la fermeture de la balise, puis ses opérations de registre sont supprimées. Il est possible d’améliorer les choses, mais nous laissons cela comme un exercice pour le lecteur.

démonstration de l'exécution de ForShops.exe
Exécution de ForShops.exe
Signal de réussite sur Windows 2019 Server
Signal de réussite sur Windows 2019 Server
capture d'écran de Beacon s'exécutant dans un processus PPL svchost
Beacon fonctionne selon un processus PPL svchost
exemple de ForShops.exe supprimant les modifications après la sortie du phare
ForShops.exe suppression des modifications après la sortie du phare

Recommandations défensives

Les conseils de détection proposés par Samir Bousseaden(@SBousseaden) après que Mohamed Fakroud a publié leur mise en œuvre s'appliquent également à cette technique de mouvement latéral :

  • Détection des événements de charge CLR dans le processus svchost.exe de WaaSMedicSvc
  • Détection de la manipulation (ou de la création) de la clé suivante dans le registre : HKLM\SOFTWARE\Classes\CLSID\{0BE35203-8F91-11CE-9DE3-00AA004BB851}\TreatAs (cléTreatAs du CLSID StandardFont)

De plus, nous recommandons de mettre en place les contrôles supplémentaires suivants :

  • Détection de la manipulation DACL de HKLM\SOFTWARE\Classes\CLSID\{0BE35203-8F91-11CE-9DE3-00AA004BB851}
  • Recherche de la présence des valeurs activées OnlyUseLatestCLR et AllowDCOMReflection dans HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework
  • Activation du pare-feu basé sur l'hôte pour restreindre l'accès au port éphémère DCOM dans la mesure du possible.

De plus, tirez parti de la règle YARA de démonstration suivante pour détecter le fichier exécutable standard ForsHops.exe :

règle Detect_Standard_ForsHops_PE_By_Hash

{
    meta:   
        description = "Detects the standard ForShops PE file by strings"
        reference = "GitHub Project: https://github.com/xforcered/ForsHops/"
    strings:
        $s1 = "System.Reflection.Assembly, mscorlib" wide
        $s2 = "{72566E27-1ABB-4EB3-B4F0-EB431CB1CB32}" wide
        $s3 = "{34050212-8AEB-416D-AB76-1E45521DB615}" wide
        $s4 = "GetType" wide
        $s5 = "Load" wide

    condition:
        all of them
}

Conclusion

Notre implémentation étend légèrement l'abus de COM expliqué dans le blog de Forshaw en exploitant les objets COM piégés pour le mouvement latéral plutôt que l'exécution locale pour le contournement de la PPL. Par conséquent, elle est toujours sensible aux mêmes détections que les implémentations effectuant une exécution locale.

Vous pouvez trouver ici le code ForsHops.exe de mouvement latéral de preuve de concept ici.

Accusé de réception

Un merci tout spécial à Dwight Hohnstein (@djhohnstein) et Sanjiv Kawa (@sanjivkawa) pour leurs commentaires sur cette recherche et pour la relecture du contenu de cet article de blog.

Ressources

Mixture of Experts | 12 décembre, épisode 85

Décryptage de l’IA : Tour d’horizon hebdomadaire

Rejoignez notre panel d’ingénieurs, de chercheurs, de chefs de produits et autres spécialistes de premier plan pour connaître l’essentiel de l’actualité et des dernières tendances dans le domaine de l’IA.

Solutions connexes
Solutions de sécurité d’entreprise

Transformez votre programme de sécurité avec le portefeuille de solutions le plus complet.

Découvrir les solutions de cybersécurité
Services de cybersécurité

Transformez votre entreprise et gérez les risques avec des services de conseil en cybersécurité, de cloud et de sécurité gérée.

    Découvrir les services de cybersécurité
    Cybersécurité et intelligence artificielle (IA)

    Accélérez et précisez le travail des équipes de sécurité, et rendez-les plus productives grâce à des solutions de cybersécurité cyberalimentées par l’IA.

    Découvrir AI cybersecurity
    Passez à l’étape suivante

    Que vous ayez besoin de solutions de sécurité des données, de gestion des points de terminaison ou de gestion des identités et des accès (IAM), nos experts sont prêts à travailler avec vous pour atteindre une excellente posture de sécurité. Transformez votre entreprise et maîtrisez vos risques avec un leader mondial de la cybersécurité, du cloud et des services de sécurité gérés.

    Découvrir les solutions de cybersécurité Découvrir les services de cybersécurité