Le support de Windows Vista Service Pack 1 (SP1) a pris fin le 12 juillet 2011. Pour continuer à recevoir des mises à jour de sécurité pour Windows, assurez-vous que vous exécutez Windows Vista avec le Service Pack 2 (SP2). Pour plus d’informations, reportez-vous à cette page web Microsoft : Le support prend fin pour certaines versions de Windows.
Lorsqu’une application charge dynamiquement une bibliothèque de liens dynamiques (DLL) sans spécifier de chemin d’accès complet, Windows tente de localiser la DLL en recherchant un ensemble bien défini de répertoires. Si un attaquant prend le contrôle de l’un des répertoires, il peut forcer l’application à charger une copie malveillante de la DLL au lieu de la DLL qu’elle attendait. Ces attaques sont appelées « attaques de préchargement de DLL » et sont communes à tous les systèmes d’exploitation qui prennent en charge le chargement dynamique des bibliothèques DLL partagées. Ces attaques peuvent avoir pour effet qu’une personne malveillante peut exécuter du code dans le contexte de l’utilisateur qui exécute l’application. Lorsque l’application est exécutée en tant qu’administrateur, cela peut entraîner une élévation de privilège locale. Nous savons qu’il y a un regain d’intérêt pour ces attaques. Pour limiter l’impact de ce problème sur nos clients mutuels, nous publions ce document à la communauté des développeurs afin qu’ils soient au courant de ce problème et disposent des outils nécessaires pour résoudre le problème dans leurs applications.
Résumé
Description des attaques de préchargement dll
Attaques basées sur LoadLibrary
Lorsqu’une application charge dynamiquement une DLL sans spécifier de chemin d’accès complet, Windows tente de localiser cette DLL en effectuant une recherche linéaire dans un ensemble bien défini de répertoires, appelé ordre de recherche de DLL. Si Windows localise la DLL dans l’ordre de recherche de DLL, il charge cette DLL. Toutefois, si Windows ne trouve pas la DLL dans l’un des répertoires dans l’ordre de recherche de DLL, il retourne un échec à l’opération de chargement de DLL. Voici l’ordre de recherche de DLL pour les fonctions LoadLibrary et LoadLibraryEx , qui sont utilisées pour charger dynamiquement des DLL :
- Répertoire à partir duquel l’application a chargé
- Répertoire système
- Répertoire système 16 bits
- Répertoire Windows
- Répertoire de travail actif (CWD)
- Répertoires répertoriés dans la variable d’environnement PATH
Prenons le scénario suivant :
- Une application charge une DLL sans spécifier de chemin d’accès complet qu’elle s’attend à trouver dans le CWD de l’application.
- L’application est entièrement préparée pour gérer le cas lorsqu’elle ne trouve pas la DLL.
- L’attaquant connaît ces informations sur l’application et contrôle la cwD.
- L’attaquant copie sa propre version spécialement conçue de la DLL dans le CWD. Cela suppose que l’attaquant a l’autorisation de le faire.
- Windows effectue une recherche dans les répertoires dans l’ordre de recherche de DLL et recherche la DLL dans le CWD de l’application.
Dans ce scénario, la DLL spécialement conçue s’exécute dans l’application et obtient les privilèges de l’utilisateur actuel.
Recommandation
Pour éviter cette attaque, les applications peuvent supprimer le répertoire de travail actuel (CWD) du chemin de recherche de DLL en appelant l’API SetDllDirectory à l’aide d’une chaîne vide (« »). Si une application dépend du chargement d’une DLL à partir du répertoire actif, obtenez le répertoire de travail actif et utilisez-le pour passer un chemin complet de LoadLibrary.
Nous savons également que certains développeurs utilisent LoadLibrary pour vérifier si une DLL spécifique est présente afin de déterminer quelle version de Windows est exécutée par l’utilisateur. Vous devez savoir que cela peut rendre l’application vulnérable. Si la bibliothèque affectée n’existe pas sur la version Windows sur laquelle l’application est exécutée, un attaquant pourrait introduire une bibliothèque portant le même nom dans CWD. Nous vous déconseillons vivement d’utiliser cette technique. Utilisez plutôt les techniques recommandées décrites dans l’article MSDN intitulé « Obtention de la version du système ».
Une application qui charge des plug-ins tiers et qui ne peut pas forcer les plug-ins à utiliser un chemin d’accès qualifié pour ses appels LoadLibrary doit appeler SetDllDirectory(« ») pour supprimer CWDllDirectory(« emplacement d’installation du plug-in ») pour ajouter le répertoire d’installation du plug-in au chemin de recherche de DLL.
Attaques basées sur SearchPath
Une attaque similaire existe lorsqu’une application utilise l’API SearchPath pour localiser une DLL et charger dynamiquement le chemin retourné par SearchPath. Voici l’ordre de recherche par défaut pour l’API SearchPath :
- Répertoire à partir duquel l’application a chargé
- Répertoire de travail actif (CWD)
- Répertoire système
- Répertoire système 16 bits
- Répertoire Windows
- Répertoires répertoriés dans la variable d’environnement PATH
Nous déconseillons ce modèle, car il n’est pas sécurisé. Nous ne recommandons pas la fonction SearchPath comme méthode de localisation d’un fichier .dll si l’utilisation prévue de la sortie est dans un appel à la fonction LoadLibrary. Cela peut entraîner la localisation du fichier .dll incorrect, car l’ordre de recherche de la fonction SearchPath diffère de l’ordre de recherche utilisé par la fonction LoadLibrary. Si vous devez localiser et charger un fichier .dll, utilisez la fonction LoadLibrary.
ShellExecute et CreateProcess
Des variantes de ces problèmes peuvent également exister lorsque les développeurs appellent des fonctions similaires telles que ShellExecute et CreateProcess pour charger des exécutables externes. Nous recommandons aux développeurs d’être prudents lorsqu’ils chargent des fichiers binaires et de spécifier le chemin d’accès complet. Cela devrait présenter moins de complexité lorsque vous chargez un fichier binaire au lieu d’une bibliothèque.
Étapes recommandées pour les développeurs de logiciels
Nous recommandons aux développeurs d’effectuer les opérations suivantes :
Validez leurs applications pour les instances de charges de bibliothèque non sécurisées (des exemples de chacune d’entre elles sont fournis plus loin dans cet article). En voici quelques exemples :
- Utilisation de SearchPath pour identifier l’emplacement d’une bibliothèque ou d’un composant.
- Utilisation de LoadLibrary pour identifier la version du système d’exploitation.
Utilisez des chemins d’accès complets pour tous les appels à LoadLibrary, CreateProcess et ShellExecute lorsque vous le pouvez.
Implémentez les appels à SetDllDirectory avec une chaîne vide (« ») pour supprimer le répertoire de travail actuel de l’ordre de recherche dll par défaut où il est nécessaire. N’oubliez pas que SetDllDirectory affecte l’ensemble du processus. Par conséquent, vous devez effectuer cette opération une fois au début de l’initialisation du processus, et non avant et après les appels à LoadLibrary. Étant donné que SetDllDirectory affecte l’ensemble du processus, plusieurs threads appelant SetDllDirectory avec des valeurs différentes peuvent entraîner un comportement non défini. En outre, si le processus est conçu pour charger des DLL tierces, des tests seront nécessaires pour déterminer si la création d’un paramètre à l’échelle du processus entraîne des incompatibilités. Un problème connu est que lorsqu’une application dépend de Visual Basic pour Applications, un paramètre à l’échelle du processus peut entraîner des incompatibilités.
Utilisez la fonction SetSearchPathMode pour activer le mode de recherche de processus sécurisé pour le processus. Cela déplace le répertoire de travail actif au dernier emplacement dans la liste de recherche SearchPath pour la durée de vie du processus.
Évitez d’utiliser SearchPath pour case activée l’existence d’une DLL sans spécifier de chemin d’accès complet, même si le mode de recherche sans échec est activé, car cela peut toujours entraîner des attaques de préchargement dll.
Conseils sur l’identification des charges de bibliothèque non sécurisées
Dans le code source, voici des exemples de chargements de bibliothèque non sécurisés :
Dans l’exemple de code suivant, l’application recherche « schannel.dll » en utilisant le chemin de recherche le moins sécurisé. Si un attaquant peut placer schannel.dll dans CWD, il se charge avant même que l’application recherche la bibliothèque appropriée dans les répertoires Windows.
DWORD retval = SearchPath(NULL, "schannel", ".dll", err, result, NULL); HMODULE handle = LoadLibrary(result);Dans l’exemple de code suivant, l’application tente de charger la bibliothèque à partir des différents emplacements d’application et de système d’exploitation décrits au début de ce document pour l’appel LoadLibrary(). S’il existe un risque que le fichier ne soit pas présent, l’application peut essayer de charger le fichier à partir du répertoire de travail actuel. Ce scénario est légèrement moins dangereux que l’exemple précédent. Toutefois, cela expose toujours l’utilisateur de l’application à des risques si l’environnement n’est pas complètement prévisible.
HMODULE handle = LoadLibrary("schannel.dll");
Voici des exemples de chargements de bibliothèque plus efficaces et plus sécurisés :
Dans l’exemple de code suivant, la bibliothèque est chargée directement à l’aide d’un chemin d’accès complet. Il n’existe aucun risque que l’attaquant introduise du code malveillant, sauf s’il dispose déjà des autorisations d’écriture sur le répertoire cible de l’application.
HMODULE handle = LoadLibrary("c:\\windows\\system32\\schannel.dll");Remarque Pour plus d’informations sur la façon de déterminer le répertoire système, consultez les ressources suivantes :
GetSystemDirectory
http://msdn.microsoft.com/en-us/library/ms724373%28VS.85%29.aspx SHGetKnownFolderPath
http://msdn.microsoft.com/en-us/library/bb762188%28v=VS.85%29.aspxDans l’exemple de code suivant, le répertoire de travail actif est supprimé du chemin de recherche avant d’appeler LoadLibrary. Cela réduit considérablement le risque, car l’attaquant doit contrôler le répertoire de l’application, le répertoire Windows ou tous les répertoires spécifiés dans le chemin d’accès de l’utilisateur afin d’utiliser une attaque de préchargement DLL.
SetDllDirectory (""); HMODULE handle = LoadLibrary("schannel.dll");Sur tous les systèmes qui ont installé la mise à jour de sécurité 963027 (décrit dans MS09-014), le code suivant déplace définitivement CWD au tout dernier emplacement dans l’ordre de recherche. Tout appel ultérieur à la fonction SetSearchPathMode à partir de ce processus qui tente de modifier le mode de recherche échoue.
SetDllDirectory (""); HMODULE handle = LoadLibrary("schannel.dll");Dans l’exemple de code suivant, le répertoire de travail actif est supprimé du chemin de recherche avant d’appeler LoadLibrary. Cela réduit considérablement le risque, car l’attaquant doit contrôler le répertoire de l’application, le répertoire Windows ou tous les répertoires spécifiés dans le chemin d’accès de l’utilisateur afin d’utiliser une attaque de préchargement DLL.
SetSearchPathMode (BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE | BASE_SEARCH_PATH_PERMANENT ); HMODULE handle = LoadLibrary("schannel.dll");
Utilisation de Process Monitor pour détecter dynamiquement les charges non sécurisées
Microsoft publie un outil nommé Process Monitor. Cet outil permet aux développeurs et aux administrateurs de suivre de près le comportement d’un processus en cours d’exécution. Process Monitor peut être utilisé pour détecter dynamiquement si l’une de vos applications peut être vulnérable à ce type de problème.
Pour télécharger Process Monitor, visitez la page web Microsoft suivante :
http://technet.microsoft.com/en-us/sysinternals/bb896645.aspxEssayez de démarrer votre application à l’aide de CWD défini sur un répertoire spécifique. Par exemple, double-cliquez sur un fichier qui a une extension dont le gestionnaire de fichiers est affecté à votre application.
Configurez Process Monitor avec les filtres suivants :
Si un chemin vulnérable est atteint, un élément similaire à ce qui suit s’affiche :
L’appel au partage de fichiers distant pour charger une DLL indique qu’il s’agit d’un programme vulnérable.
Informations supplémentaires
Pour plus d’informations, visitez les pages web Microsoft suivantes :
Ordre de recherche de la bibliothèque de liens dynamiques
http://msdn.microsoft.com/en-us/library/ms682586(VS.85).aspx Documentation MSDN sur la fonction SearchPath
http://msdn.microsoft.com/en-us/library/aa365527(VS.85).aspx Documentation MSDN sur la fonction LoadLibrary
http://msdn.microsoft.com/en-us/library/ms684175(VS.85).aspx Documentation MSDN sur la fonction SetDllDirectory
http://msdn.microsoft.com/en-us/library/ms686203(VS.85).aspx Documentation MSDN sur la fonction SetSearchPathMode
http://msdn.microsoft.com/en-us/library/dd266735(VS.85).aspx Billet de blog de David Leblanc, Ingénieur sécurité principal chez Microsoft Office
http://blogs.msdn.com/b/david_leblanc/archive/2008/02/20/dll-preloading-attacks.aspx Billet de blog d’Andrew Roths, équipe d’ingénierie MSRC sur les attaques de préchargement de DLL