Contribuez à SecuObs en envoyant des bitcoins ou des dogecoins.
Nouveaux articles (fr): 1pwnthhW21zdnQ5WucjmnF3pk9puT5fDF
Amélioration du site: 1hckU85orcGCm8A9hk67391LCy4ECGJca

Contribute to SecuObs by sending bitcoins or dogecoins.



[Sécurité avec Microsoft Internet Explorer – Partie 5] Exploitation de Google Desktop et exécution distante de code

Par Krysztof Kozlowski, hakin9
Le 22/10/2007


Résumé : Retrouvez ici les explications théoriques sur l'exploitation de la faille Google Desktop et Microsoft Internet Explorer, faille qui a déjà été présentée de façon générale dans la troisième partie de ce dossier, rappelons qu'elle permet de divulguer à travers MSIE6 des informations sensibles via les résultats d'indexation des fichiers et des messages locaux par Google Desktop.



Afin de montrer comment on pouvait profiter de cette faiblesse, on pouvait préparé un script qui exploitait Google Desktop Search (GDS) pour chercher et intercepter les données privées des utilisateurs via une page distante. Une des caractéristiques de GDS était le fragment du code qui était utilisé pour l'indexation des données de l'utilisateur ; pour l'indexation il prenait en compte l'ensemble des documents, des messages électroniques, etc etc.

Une fois les données indexées, l'utilisateur pouvait faire des recherches dans les fichiers à l'aide de l'interface similaire à celle dont était dotée à l'époque Google.com. La recherche s'effectuait à l'aide du serveur http installé sur un ordinateur local ; le serveur écoutait sur le port 4664 et il n'était relié qu'à l'ordinateur local 127.0.0.1, ce qui rendait impossible la connexion directe depuis l'extérieur.

Google ayant ajouté également une protection supplémentaire pour rendre impossible l'accès des parties externes au serveur local d'où le fait que les tentatives d'exploiter les failles XSS simples échouaient. Pour accéder à l'interface GDS, on générait une clé pseudo aléatoire à transmettre en paramètre dans l'adresse URL.

La clé était générée au moment où l'utilisateur cliquait sur l'icône GDS et le navigateur par défaut se connectait au serveur en utilisant la clé générée. Si la clé était erronée ou absente, GDS ne permettait d'effectuer aucune requête et retournait un message d'erreur. Dans un tel cas, le navigateur ne pouvait accéder qu'à une image au format gif (le logo de Google).

Google a de plus intégré GDS à Google.com ; après l'installation de GDS, on voyait s'afficher un lien dans Google.com au dessus du champ de requête. Le lien s'appelait Desktop, il menait à l'adresse URL du serveur local et contenait une clé. Grâce à cela, l'utilisateur pouvait passer à la recherche des fichiers locaux sans remarquer qu'il quittait la page de Google. Le lien desktop ne provenait pas en fait de Google mais il était injecté directement par GDS via un plug-in du navigateur dès qu'il considérait qu'on visitait une page Google.

Cette démarche était censé protéger l'utilisation contre la sortie de la clé vers l'extérieur. Afin de se servir de la faille de GDS, l'attaquant devait trouver dans un premier temps la clé. Il était difficile d'accéder au serveur local sans cette clé ; comme il a déjà été mentionné, la clé existait dans un lien sur la page de Google, c'est donc l'endroit où on l'on pouvait la récupérer à l'aide d'une attaque de type CSSXSS.

Vu la conception à l'époque des pages Google, l'interception du lien n'était pas possible sur la plupart de ses pages ; malgré cela, il existait une technique utilisant ce lien qui pouvait être détourné via la page Google News et le FQDN news.google.com. Il suffisait alors d'injecter des caractères de type accolades dans la requête transportée par l'URL ; il était ensuite nécessaire de récupérer la clé à l'aide d'expressions régulières et de l'importation CSS sur l'adresse du serveur local.

Il était également possible d'ajouter une accolade à la requête afin de voir les résultats s'afficher aussi dans la propriété cssText après l'analyse par CSS. Ce caractère était ignoré par le moteur du navigateur et n'influençait pas les résultats.

Cet exemple fonctionnait avec la version la plus récente (correctifs inclus) de Microsoft Internet Explorer (avec les paramètres de protection et d'options privées par défaut) et avec la version 2 de Google Desktop ; il ne fonctionnait pas avec d'autres navigateurs à moins qu'ils ne soient que des sur-couches à Microsoft Internet Explorer.

Les résultats pouvaient être aussi différents en fonction de la version linguistique et de la conception de la page Google News du moment ainsi que du contenu du disque de la victime (et de la version linguistique de GDS).


Exécution distante du code

C'est le message bien connu « unhandled exception » qui apparaissaient dans différentes situations sous les systèmes d'exploitation Microsoft Windows. Les erreurs, dont le système d'exploitation nous informait, pouvaient permettre d'exécuter un code spécifique préparé préalablement. Avoir le contrôle sur le filtre de ces exceptions était le point le plus important pour un attaquant ; depuis la version Service Pack 2 (SP2 - lien ), certaines protections du contrôle de ces exceptions étaient apparues mais là encore malgré ces améliorations, il était toujours possible de contrôler le filtre sur les niveaux les plus élevés.

Cela était possible à cause d'une faille de conception de Microsoft Internet Explorer, et plus précisément à cause de la manière dont les filtres d'exceptions étaient liés entre eux. Cette approche était aussi restreinte car l'attaquant ne pouvait contrôler que les liaisons entre les filtres, comme le chargement ou la libération des bibliothèques. Une méthode simple consistait alors à utiliser directement les failles de Microsoft Internet Explorer.

Ces failles pouvaient être divisées en deux groupes : celles qui permettaient d'exécuter du code directement et celles qui ne le permettaient pas. Il était ainsi possible de déterminer si une faille donnée pouvait être utilisée par l'attaquant ou pas en vue de son exploitation et de la corruption d'un système d'exploitation. De nombreuses failles du premier groupe étaient cependant inoffensives car elles n'avaient rien à voir avec la mémoire tampon ; de nombreuses failles s'avéraient cependant être sensibles à leur exploitation par des attaques.

Il fallait alors réfléchir au fait qu'une faille donnée pouvait influencer l'exécution du code à l'aide d'une autre application ; à titre d'exemple, l'appel de NULL pointer faisait transgresser les droits d'accès et le gestionnaire des exceptions critiques réagissait de manière adéquate et cela à condition d'avoir une instruction appropriée lors de l'appel. Si aucun des gestionnaires ne savait quoi faire, le filtre d'exceptions du plus haut niveau était appelé ; ce filtre du nom de Unhandled Exception Filter ou UEF de plus haut niveau.

C'était kernel32!UnhandledExceptionFilter qui l'appelait (s'il avait été paramétré) ; mis à part ce mécanisme, l'attaquant n'avait pas beaucoup de choix si les autres conditions n'étaient pas remplies. Pour cette raison, le meilleur endroit afin de trouver des failles de ce type était le processus de gestion d'exceptions lui-même.

La première étape de la gestion et de la distribution des exceptions consistait à appeler les fils enregistrés pour des exceptions données ; ceci permettait de déterminer quelles exceptions étaient contrôlées et comment. Si aucune des exceptions enregistrées ne pouvait être contrôlée, il fallait trouver une méthode pour rediriger le gestionnaire d'exceptions ou son filtre. On pouvait le faire en modifiant le pointeur pour qu'il appelle le code que l'on avait préalablement défini. Depuis la sortie du Service Pack 2, il était beaucoup plus difficile d'écraser la variable globale contenant l'UEF du niveau le plus élevé.

Afin de permettre aux applica­tions de gérer les exceptions, le gestionnaire fournissait une interface pour les enregistrer. Grâce à cette interface, il était possible de récolter les informations, de récupérer et de gérer les exceptions spécifiques pour le langage donné ; afin de définir et d'enregistrer une exception, il fallait utiliser kernel32!SetUnhandledExceptionFilter qui fonctionnait de la manière suivante :

LPTOP _LEVEL _EXCEPTION _FILTER SetUnhandledExceptionFilter(
LPTOP _LEVEL _EXCEPTION _FILTER lpTopLevelExceptionFilter
);


Au moment de l'appel, cette fonction montrait l'argument lpTopLevelExceptionFilter et le code à l'aide de kernel32!RtlEncodePointer. Le résultat était stocké dans la variable globale : kernel32!BasepCurrentTopLevelFilter et redirigé à un des filtres de haut niveau. La valeur enregistrée avec la variable globale était décodée par kernel32!RtlDecodePointer et retournée à l'utilisateur. Le codage et le décodage servaient à rendre impossible pour l'attaquant l'utilisation d'une quantité supplémentaire de la mémoire pour la redirection.

La fonction kernel32!SetUnhandledExceptionFilter retournait le pointeur au niveau original élevé pour deux raisons. Premièrement, il était ainsi possible de restituer l'état dans l'avenir et deuxièmement, il était possible de créer une chaîne. Si un bloc de code inscrivait une exception en UEF, l'UEF la désinscrivait lui-même. Il l'effectuait en paramétrant la première valeur en UEF soit : kernel32!SetUnhandledExceptionFilter.

En réalité, une vraie liste d'exceptions contrôlée par les filtres n'existait pas. La méthode d'inscription était la clé pour l'attaquant. Les opérations d'inscription et de désinscription devaient être effectuées de manière symétrique. Si l'exception passait toutes les étapes et n'était pas gérée, le distributeur d'exceptions effectuait une autre opération avant de forcer l'application à se fermer.

L'une des options consistait à envoyer l'application au débogueur s'il était actif. Sinon, il devait gérer l'exception de l'intérieur ou fermer l'application si la démarche échouait. Pour rendre cela impossible à un attaquant, les applications devaient appeler le filtre d'exceptions lié au processus. Dans la plupart des cas, le résultat était le suivant : kernel32!UnhandledExceptionFilter donc l'appel de l'instruction avec l'information sur la redirection de l'exception.

Le kernel32 !UnhandledExceptionFilter réalisait en réalité deux choses. Premièrement, lorsque le débogueur n'était pas disponible, il appelait l'UEF du haut niveau pour enregistrer le processus. L'UEF du haut niveau tentait de gérer l'exception en permettant probablement à l'application de travailler, par exemple à l'aide de : EXCEPTION _ CONTINUE _ EXECUTION. Si cette démarche échouait, le processus était supprimé probablement à l'aide de EXCEPTION _ EXECUTE _ HANDLER ou bien une boîte de dialogue avec le message standard EXCEPTION _ CONTINUE _SEARCH s'affichait.

Si le débogueur était disponible, le filtre d'exceptions essayait de rediriger l'exception vers le débogueur. Dans un tel cas, l'UEF du haut niveau n'était alors pas appelé ; lors du travail effectué sur le système avec un débogueur qui était indisponible, kernel32!UnhandledExceptionFilter tentait de décoder le pointeur lié à l'UEF du plus haut niveau en appelant kernel32!RtlDecodePointer dans la variable globale, contenant UEF soit kernel32!BasepCurrentTopLevelFilter :

7c862cc1 ff35ac33887c push dword ptr [ kernel32!BasepCurrentTopLevelFilter]
7c862cc7 e8e1d6faff call kernel32!RtlDecodePointer (7c8103ad)



Si la valeur retournée par kernel32!RtlDecodePointer est différente de NULL, on appelait l'UEF décodé à ce moment là, l'information sur l'exception était alors retransmise :

7c862ccc 3bc7 cmp eax,edi
7c862cce 7415 jz kernel32!UnhandledExceptionFilter +0x15b (7c862ce5)
7c862cd0 53 push ebx
7c862cd1 ffd0 call eax



Cette valeur décidait si l'application continuait de travailler ou si elle était interrompue et si on affichait une erreur ou non. Dans la plupart des cas, les filtres d'exceptions étaient utilisés pour gérer les exceptions caractéristiques pour un langage donné.

A titre d'exemple, le code C++ enregistrait l'exception via CxxSetUnhandledExceptionFilter lors de l'initialisation CRT (C Run-Times Libraries - lien ) pendant le chargement des bibliothèques. Il désinscrivait l'exception via CxxRestoreUnhandledExceptionFilter en terminant le programme ou en libérant les bibliothèques.


NB : Il est possible de s'abonner au magazine Hakin9 et d'acheter directement le dernier numéro ou d'anciens numéros, en cliquant sur l'image ci-dessous :

Software-Wydawnictwo



Autres ressources dans ce dossier :

[Sécurité avec Microsoft Internet Explorer – Partie 1] Introduction et rappel – lien

[Sécurité avec Microsoft Internet Explorer – Partie 2] Présentation et statistiques - lien

[Sécurité avec Microsoft Internet Explorer – Partie 3] Attaques sur l'application Google Desktop - lien

[Sécurité avec Microsoft Internet Explorer – Partie 4] Cascading Style Sheets Cross Site Scripting ou CSSXSS - lien

[Sécurité avec Microsoft Internet Explorer – Partie 6] Prise de contrôle du filtre d'exceptions critiques - lien

[Sécurité avec Microsoft Internet Explorer – Partie 7] Crédits & références - lien