Vous avez besoin du Cloud Computing ? Commencez dès maintenant

Hâte de vous éteindre – DoS distant utilisant Wininit.exe

Stiv Kupchik

écrit par

Stiv Kupchik

January 31, 2023

Stiv Kupchik

écrit par

Stiv Kupchik

Stiv Kupchik est Senior Security Researcher et est basé à Tel Aviv, en Israël.

Wininit is a critical Windows process, playing a crucial role in both the start up and shut down of the Windows operating system (to the tune of – if it crashes, the whole system crashes).

Contributions éditoriales et additionnelles de Tricia Howard

Synthèse

  • Stiv Kupchik, chercheur chez Akamai, a trouvé une nouvelle vulnérabilité de déni de service (DoS) dans Wininit.exe de Microsoft, CVE-2022-44707, obtenu un score CVSS de 6,5.

  • La vulnérabilité a été révélée de manière responsable à MSRC en août et a été corrigée dans le cadre du Patch Tuesday de décembre 2022.

  • La vulnérabilité exploite le mécanisme de mise en cache RPCsur lequel nous avons fait des recherches approfondies. Nous fournissons une démonstration de cette attaque dans notre boîte à outils RPC.

  • En exploitant cette vulnérabilité, un pirate peut contourner une vérification de sécurité grâce au mécanisme de mise en cache et interagir avec le mécanisme d'arrêt sur un ordinateur Windows distant. Il devient alors capable d'initier et de stopper des arrêts.

  • Cette vulnérabilité affecte toutes les versions non corrigées de Windows, à partir de Windows 8/Server 2012, ce qui renforce l'importance de la mise en œuvre rapide de correctifs.

Introduction

Dans notre article précédent, La dure réalité du cache, nous avons annoncé la future révélation de quelques vulnérabilités RPC supplémentaires que nous avons trouvées à l'aide de notre boîte à outils RPCet le temps est enfin venu de vous les présenter. Aujourd'hui, dans la liste des manigances exploitant RPC, nous analysons Wininit.  

Wininit est un processus Windows critique qui joue un rôle crucial dans le démarrage et l'arrêt du système d'exploitation Windows (à tel point que s'il s'arrête, l'ensemble du système s'arrête). À ce titre, il expose plusieurs interfaces RPC qui mettent en œuvre la fonctionnalité d'arrêt. Certaines d'entre elles sont même documentées. La vulnérabilité que nous avons trouvée se trouve dans l'interface WindowsShutdown.

Qu'est-ce que l'interface WindowsShutdown ?

WindowsShutdown est l'une des rares interfaces RPC exposées par Wininit. Elle est responsable du processus d'arrêt, tout comme le reste des interfaces RPC de Wininit (quelle surprise !). L'UUID de l'interface est d95afe70-a6d5-4259-822e-2c84da1ddb0d. Elle fait partie du MS-RSP (Remote Shutdown Protocol, protocole d'arrêt à distance) et offre les fonctionnalités suivantes : 

WindowsShutdown exposed functions: WsdrInitiateShutdown, WsdrAbortShutdown and WsdrCheckForHiberboot Fig. 1: The capabilities of of the WindowsShutdown interface

En étudiant le fichier IDL public, nous pouvons constater que seuls WsdrInitiateShutdown et WsdrAbortShutdown sont documentés. Devrions-nous nous soucier d'une fonction non documentée ? (Une question qu'aucun chercheur n'a jamais posée.) Pour y répondre, examinons le rappel de sécurité de cette interface.

Le rappel de sécurité

Le rappel vérifie d'abord le protocole de transport et autorise uniquement ALPC ou TCP. Ensuite, le niveau d'authentification est vérifié et seul RPC_C_AUTHN_LEVEL_PKT_PRIVACY est autorisé. Si la fonction appelée n'est pas WsdrCheckForHiberboot, le jeton de l'utilisateur appelant distant est vérifié. Pour cela, le jeton est comparé avec un SID bien connu (enregistré dans une variable globale créée lors de l'initialisation de Wininit) : SECURITY_NETWORK_RID. Les appels à WsdrCheckForHiberboot ne sont pas du tout limités par le rappel de sécurité.

décompilation de la fonction de rappel de sécurité de WindowsShutdown Fig. 2: The security callback for WindowsShutdown

L'interface RPC est enregistrée avec le comportement de cache par défaut. Donc, théoriquement, si nous pouvions appeler avec succès WsdrCheckForHiberboot, le résultat mis en cache réussi nous permettrait de contourner la vérification SID sur les appels suivants pour WsdrInitiateShutdown et WsdrAbortShutdown.

Alors, que devons-nous faire pour appeler WsdrCheckForHiberboot

WsdrCheckForHiberboot

Nous ne nous soucions pas vraiment de ce que fait la fonction ou de ce qu'est l'« hiberboot » (pour ceux qui se le demandent, il s'agit du démarrage rapide de Windows), mais nous avons besoin de savoir comment l'appeler correctement. Nous voulons définir la fonction correctement dans un fichier IDL afin de lui compiler un client. Bien que la fonction ne soit pas documentée, nous pouvons essayer de regarder l'advapi CheckForHiberboot, le seul client RPC documenté que nous avons trouvé pour WsdrCheckForHiberboot. Il ne requiert que deux arguments : un pointeur de booléen et un booléen.

advapi32 disassembly of CheckForHiberboot Fig. 3: The advapi CheckForHiberboot — the only documented RPC client we found for WsdrCheckForHiberboot

Nous pouvons recréer la définition de fonction avec ces arguments, en compilant un fichier et un programme IDL. Mais il manque encore quelque chose. Lorsque nous appelons la fonction à distance avec notre client, l'exécution RPC nous indique que nous appelons la fonction de manière incorrecte en renvoyant une erreur de stub RPC.

initial recreation of WsdrCheckForHiberboot definition, based on the advapi function Fig. 4: The first recreation of WsdrCheckForHiberboot definition

Au lieu de poursuivre les conjectures, nous pouvons entreprendre quelque chose de plus délicat, mais complexe. Dans le cadre du stub de l'interface RPC, nous trouvons un champ appelé ProcFormatString. Pour faire simple, il s'agit d'une longue chaîne binaire qui décrit les types d'arguments et les valeurs de retour pour toutes les fonctions exposées par l'interface. Ce champ est utilisé par l'exécution RPC pendant la sérialisation et la désérialisation des appels de fonction (qui est le processus qui a renvoyé l'erreur de stub RPC lors de notre première tentative). En analysant manuellement et avec minutie cette chaîne binaire, nous avons finalement découvert que la fonction s'attend à obtenir un autre argument (du type wchar_t*). Dans la figure suivante, vous pouvez voir la section du ProcFormatString de WsdrCheckForHiberboot, avec nos propres commentaires concernant chaque partie :

initial recreation of WsdrCheckForHiberboot definition, based on the advapi function Fig. 5: The section of WsdrCheckForHiberboot from the ProcFormatString

L'ajout de ce « nouvel » argument à notre définition de fonction a complètement débloqué la situation. CheckForHiberboot renvoie avec succès, et nous pouvons continuer à appeler à la fois WsdrInitiateShutdown et WsdrAbortShutdown.

Mais, ce n'est pas tout à fait fini…

Notre objectif immédiat est d'utiliser l'attaque par mise en cache pour appeler WsdrInitiateShutdown et d'effectuer un arrêt à distance. Cette fois-ci, il n'y a pas de conjectures. Non seulement la définition de la fonction est documentée dans le fichier IDL, mais les indicateurs qu'elle prévoit obtenir sont documentés sous la fonction advapi InitiateShutdownA. Ainsi, en utilisant la combinaison d'indicateurs SHUTDOWN_GRACE_OVERRIDE, SHUTDOWN_HYBRID et SHUTDOWN_FORCE_OTHERS, nous pouvons forcer un arrêt immédiat.

Grâce à cela, nous avons fini notre chaîne d'attaque et ainsi pu contourner le rappel de sécurité et sa vérification SID, et effectuer l'arrêt à distance. Techniquement, il s'agit d'une augmentation des droits (permettant à tout utilisateur authentifié d'appeler WsdrInitiateShutdown à distance au lieu de se restreindre à celles autorisées dans SECURITY_NETWORK_RID). Comme nous ne pouvons effectuer un arrêt qu'avec l'aide de cette interface, la vulnérabilité a été classée dans la catégorie vulnérabilité DoS.

Détection

Nous fournissons un OSQuery pour détecter les versions non corrigées (et donc vulnérables) de Wininit.exe. Pour identifier les ressources vulnérables, les clients dotés de la technologie Guardicore Segmentation d'Akamai peuvent utiliser la fonction d'information avec cette requête.

  WITH product_version AS (
  WITH os_minor AS (
    WITH os_major AS (
      SELECT substr(product_version, 0, instr(product_version, ".")) as os_major, substr(product_version, instr(product_version, ".")+1) as no_os_major_substr
      FROM file
      WHERE path = "c:\windows\system32\wininit.exe"
    )
    SELECT substr(no_os_major_substr, instr(no_os_major_substr, ".")+1) as no_os_minor_substr, substr(no_os_major_substr, 0, instr(no_os_major_substr, ".")) as os_minor, os_major
    FROM os_major
  )
  SELECT
    CAST(substr(no_os_minor_substr, instr(no_os_minor_substr, ".")+1) AS INTEGER) AS product_minor,
    CAST(substr(no_os_minor_substr, 0, instr(no_os_minor_substr, ".")) AS INTEGER) AS product_major,
    CAST(os_minor AS INTEGER) AS os_minor,
    CAST(os_major AS INTEGER) AS os_major
  FROM os_minor
)
SELECT
  CASE
    WHEN NOT ((os_major = 6 AND os_minor = 3) OR (os_major = 6 AND os_minor = 2) OR (os_major = 10 AND os_minor = 0))
    THEN "not supported"
    WHEN os_major = 6 AND os_minor = 3 AND product_major = 9600 AND product_minor >= 20716 THEN "patched"
    WHEN os_major = 6 AND os_minor = 2 AND product_major = 9200 AND product_minor >= 24011 THEN "patched"
    WHEN (
        (product_major = 14393 AND product_minor >= 5582)
        OR
        (product_major = 10240 AND product_minor >= 19624)
        OR
        (product_major = 19041 AND product_minor >= 1620)
        OR
        (product_major = 22621 AND product_minor >= 963)
        OR
        (product_major = 22000 AND product_minor >= 1335)
        OR
        (product_major = 20348 AND product_minor >= 1366)
        OR
        (product_major = 17763 AND product_minor >= 3770)
    )
    THEN
      "patched"
    ELSE
      "not patched"

Synthèse

Bien que cette vulnérabilité ne soit pas critique (il s'agit juste d'un arrêt à distance, authentifié qui plus est), il démontre le potentiel destructeur inhérent de MS-RPC, car il est intégré même dans les services les plus critiques du système d'exploitation Windows. En outre, contrairement à d'autres types de vulnérabilités, il n'y a presque aucune conjecture concernant RPC : toutes les cartes sont sur la table (binaire), il suffit de savoir les lire.

Trouver des moyens d'exploiter ces fonctions critiques est précisément la raison pour laquelle nous continuons nos recherches approfondies sur MS-RPC. Dans un contexte global, en dépit de son utilisation généralisée, il est largement sous-étudié. Des vulnérabilités comme celle abordée aujourd'hui montrent la nécessité de ce type de travail, et nous avons hâte de voir d'autres chercheurs travailler sur MS-RPC s'ils le souhaitent. 

Cette vulnérabilité a été révélée de manière responsable à la fin du mois d'août et corrigée dans le Patch Tuesday de décembre 2022.



Stiv Kupchik

écrit par

Stiv Kupchik

January 31, 2023

Stiv Kupchik

écrit par

Stiv Kupchik

Stiv Kupchik est Senior Security Researcher et est basé à Tel Aviv, en Israël.