Considérations relatives à la sécurité : interface utilisateur Windows
Cette rubrique fournit des informations sur les considérations de sécurité relatives à l’interface utilisateur Windows. Cette rubrique n’offre pas tout ce dont vous devez savoir en matière de problèmes de sécurité. Utilisez-la plutôt comme point de départ et référence pour ce domaine technologique.
Avec l’augmentation de l’interconnectivité des ordinateurs, les développeurs doivent désormais se préoccuper de la sécurité des applications. Toutefois, la sécurité améliore également la robustesse et la sécurité générale des applications ; il s’agit donc d’un autre moyen pour le développeur de pouvoir offrir une bonne expérience utilisateur. Les rubriques suivantes évoquent certains problèmes de sécurité potentiels lors de l’utilisation de l’interface utilisateur Windows.
De nombreuses fonctions, messages et macros utilisent des chaînes dans leurs paramètres. Toutefois, les chaînes ne sont pas souvent vérifiées en ce qui concerne la terminaison nulle ou la longueur. Une préoccupation associée consiste à mal calculer la longueur d’une chaîne ou d’une mémoire tampon. Dans les deux cas, cela peut entraîner un dépassement de mémoire tampon ou une troncation des données qui peut affecter votre application de manière défavorable. Pour obtenir plus d’informations sur les dépassements de mémoire tampon et d’autres problèmes de sécurité, consultez Writing Secure Code (en anglais) par Michael Howard et David Leblanc, Microsoft Press, 2002.
Pour gérer des chaînes de manière sécurisée, vous devez effectuer les opérations suivantes :
- Vérifiez les chaînes en matière de terminaison nulle ou de longueur appropriée, le cas échéant.
- Veillez à déterminer la longueur d’une chaîne ou d’une mémoire tampon, en particulier lorsqu’elle contient des valeurs TCHAR.
- Si vous créez une chaîne ou utilisez une chaîne qui a été précédemment utilisée, initialisez-la sur zéro ou insérez un caractère nul, le cas échéant.
En outre, envisagez d’utiliser les fonctions StrSafe lorsque vous gérez des chaînes. Ces fonctions sont conçues pour gérer les chaînes en toute sécurité.
L’interface utilisateur Windows est concerné par l’obtention et la réponse aux informations des utilisateurs. Toutefois, les utilisateurs qui entrent des données incorrectes peuvent perturber votre application, qu’ils le fassent volontairement ou non. Par conséquent, la règle cardinale est que toutes les entrées doivent être validées.
Les données de chaîne constituent l’une des principales préoccupations et elle est évoquée dans Considérations relatives aux chaînes. Toutefois, tous les types d’entrée doivent être validés avant leur utilisation par votre application. Une autre préoccupation est lorsque les données sont validées à un moment donné, mais qu’elles changent avant leur utilisation, par exemple lors de la réception de messages qui fournissent la longueur du texte. Par conséquent, s’il est possible que les données changent, vous devez vérifier les données juste avant de les utiliser
Le tableau suivant répertorie les fonctionnalités qui, en cas d’utilisation incorrecte, peuvent compromettre la sécurité de vos applications.
Fonctionnalité | Atténuation |
---|---|
GetAtomName | Veillez à spécifier soigneusement la taille de la mémoire tampon. |
GlobalGetAtomName | Les atomes de chaîne globaux sont accessibles à n’importe quelle application. Toutefois, si une autre application est imprudente, elle peut mal gérer le nombre de références et les supprimer. Vous devez envisager d’utiliser des atomes entiers globaux à la place. |
ImpersonateDdeClientWindow | Si la fonction échoue, les demandes du client suivantes sont effectuées dans le contexte de la sécurité du processus appelant. Il peut constituer un problème si le processus appelant s’exécute en tant que compte hautement privilégié. Par conséquent, si l’appel échoue ou déclenche une erreur, ne continuez pas l’exécution de la demande client. |
DdeImpersonateClient | Si la fonction échoue, les demandes du client suivantes sont effectuées dans le contexte de la sécurité du processus appelant. Il peut constituer un problème si le processus appelant s’exécute en tant que compte hautement privilégié. Par conséquent, si l’appel échoue ou déclenche une erreur, ne continuez pas l’exécution de la demande client. |
GetClipboardFormatName | Le calcul incorrect de la taille appropriée de la mémoire tampon lpszFormatName, en particulier lorsque l’application est utilisée dans les versions ANSI et Unicode, peut entraîner un dépassement de mémoire tampon. Notez également que la chaîne est tronquée si elle est plus longue que le paramètre cchMaxCount, ce qui peut entraîner une perte d’informations. |
GetMenuString | Le paramètre lpString est une mémoire tampon TCHAR et nMaxCount est la longueur de la chaîne de menu dans des TCHAR. Le dimensionnement incorrect de ces paramètres peut être la longueur de la chaîne de menu en caractères. Le dimensionnement incorrect de ces paramètres peut entraîner une troncation de la chaîne, ce qui peut entraîne une perte de données. |
GetStringTypeA, GetStringTypeEx, GetStringTypeW | Pour éviter un dépassement de mémoire tampon, définissez correctement la taille de la mémoire tampon lpCharType. |
LoadLibrary | L’utilisation incorrecte de LoadLibrary peut compromettre la sécurité de votre application en chargeant la mauvaise bibliothèque de liens dynamiques. |
LoadString | L’utilisation incorrecte inclut la spécification de la taille incorrecte dans le paramètre nBufferMax. Par exemple, sizeof(lpBuffer) donne la taille de la mémoire tampon en octets, ce qui peut entraîner un dépassement de mémoire tampon pour la version Unicode de la fonction. Les situations de dépassement de mémoire tampon sont la cause de nombreux problèmes de sécurité dans des applications. Dans ce cas, l’utilisation de sizeof(lpBuffer)/sizeof(TCHAR) donne la taille appropriée de la mémoire tampon. |
lstrcat | Cette fonction utilise une gestion structurée des exceptions (SEH) pour intercepter les violations d’accès et d’autres erreurs. Lorsque cette fonction intercepte des erreurs SEH, elle retourne NULL sans terminaison nulle de la chaîne et sans NULL sans la terminaison nulle de la chaîne et sans informer l’appelant de l’erreur. L’appelant n’est pas sûr de supposer que l’espace insuffisant est la condition de l’erreur. Le premier argument, lpString1, doit être suffisamment grand pour contenir lpString2 et la fermeture « \0 », sinon un dépassement de mémoire tampon peut se produire. Les dépassements de mémoire tampon peuvent entraîner une attaque par déni de service sur l’application si une violation d’accès se produit. Dans le pire des cas, un dépassement de mémoire tampon peut permettre à un attaquant d’injecter du code exécutable dans votre processus, en particulier si lpString1 est une mémoire tampon basée sur la pile. Envisagez d’utiliser l’une des options suivantes. StringCbCat or StringCchCat. |
lstrcpy | Cette fonction utilise une gestion structurée des exceptions (SEH) pour intercepter les violations d’accès et d’autres erreurs. Lorsque cette fonction intercepte des erreurs SEH, elle retourne NULL sans terminaison nulle de la chaîne et sans NULL sans la terminaison nulle de la chaîne et sans informer l’appelant de l’erreur. L’appelant n’est pas sûr de supposer que l’espace insuffisant est la condition de l’erreur. Le premier argument, lpString1, doit être suffisamment grand pour contenir lpString2 et la fermeture « \0 », sinon un dépassement de mémoire tampon peut se produire. Les dépassements de mémoire tampon peuvent entraîner une attaque par déni de service sur l’application si une violation d’accès se produit. Dans le pire des cas, un dépassement de mémoire tampon peut permettre à un attaquant d’injecter du code exécutable dans votre processus, en particulier si l’argument lpString1 est une mémoire tampon basée sur la pile. Envisagez plutôt d’utiliser StringCchCopy. |
lstrcpyn | Cette fonction utilise une gestion structurée des exceptions (SEH) pour intercepter les violations d’accès et d’autres erreurs. Lorsque cette fonction intercepte des erreurs SEH, elle retourne NULL sans terminaison nulle de la chaîne et sans NULL sans la terminaison nulle de la chaîne et sans informer l’appelant de l’erreur. L’appelant n’est pas sûr de supposer que l’espace insuffisant est la condition de l’erreur. Si l’argument lpString1 n’est pas suffisamment grand pour contenir la chaîne copiée, un dépassement de mémoire tampon peut se produire. En outre, lorsque vous copiez une chaîne entière, notez que sizeof retourne le nombre d’octets plutôt que WCHAR, que sizeof renvoie le nombre d’octets plutôt que des caractères, ce qui est incorrect pour la version Unicode de cette fonction. Les dépassements de mémoire tampon peuvent provoquer une attaque par déni de service sur l’application si une violation d’accès se produit. Dans le pire des cas, un dépassement de mémoire tampon peut permettre à un attaquant d’injecter du code exécutable dans votre processus, en particulier si l’argument lpString1 est une mémoire tampon basée sur la pile. Envisagez plutôt d’utiliser StringCchCopy. |
lstrlen | lstrlen suppose que lpString est une chaîne terminée par NULL. Si ce n’est pas le cas, cela peut entraîner un dépassement de mémoire tampon ou une attaque par déni de service sur votre application. Envisagez d’utiliser l’une des options suivantes. StringCbLength ou StringCchLength. |
wsprintf | Il n’est pas garanti que la chaîne retournée dans lpOut se termine par NULL. De même, évitez le format %s qui peut entraîner un dépassement de mémoire tampon. Si une violation d’accès se produit, elle provoque un déni de service sur votre application. Dans le pire des cas, un attaquant peut injecter du code exécutable. Envisagez d’utiliser l’une des options suivantes. StringCbPrintf, StringCbPrintfEx, StringCbVPrintf, StringCbVPrintfEx, StringCchPrintf, StringCchPrintfEx, StringCchVPrintf ou StringCchVPrintfEx. |
wvsprintf | Il n’est pas garanti que la chaîne retournée dans lpOutput se termine par NULL. En outre, évitez d’utiliser le format %s qui peut entraîner un dépassement de mémoire tampon. Cela peut entraîner un déni de service s’il cause une violation d’accès, ou un attaquant peut injecter du code exécutable. Envisagez d’utiliser l’une des options suivantes. StringCbPrintf, StringCbPrintfEx, StringCbVPrintf, StringCbVPrintfEx, StringCchPrintf, StringCchPrintfEx, StringCchVPrintf ou StringCchVPrintfEx. |