Partager via


Bonnes pratiques de sécurité dans le développement de jeux

Cet article décrit les meilleures pratiques à utiliser dans le développement de jeux.

Introduction

Un nombre croissant de personnes jouent à des jeux en ligne et à des jeux avec du contenu créé par l’utilisateur. Ceci, combiné à la sécurité croissante du système d’exploitation Microsoft Windows, signifie que les jeux sont une cible croissante et plus tentante pour les attaquants d’exploiter. Les développeurs de jeux doivent mettre l’accent sur le fait que les jeux qu’ils publient ne créent pas de failles de sécurité pour les attaquants. Les développeurs de jeux ont la responsabilité et l’intérêt d’aider à empêcher les ordinateurs de leurs clients d’être piratés par des données réseau malveillantes, des modifications d’utilisateurs ou des falsifications. Si une vulnérabilité est exploitée, elle peut entraîner la perte de clients et/ou d’argent. Cet article décrit et explique certaines méthodes et outils courants permettant d’améliorer la sécurité du code sans surcharger le temps de développement.

Les trois erreurs les plus courantes commises par une équipe de développement lors de la publication d’un produit sont les suivantes :

  • Exiger des privilèges d’administration. Les jeux ne doivent pas nécessiter de privilèges administratifs. Pour plus d’informations, consultez Contrôle de compte d’utilisateur pour les développeurs de jeux.
  • N’utilisez pas la protection automatisée. Les développeurs n’utilisent généralement pas /GS, /SAFESEH ou /NX. L’utilisation de ces indicateurs de compilation/de liaison peut repérer ou éliminer de nombreux trous de sécurité de base sans augmenter considérablement la charge de travail. Ces indicateurs sont abordés plus loin dans cet article.
  • Utilisation d’API interdites. De nombreuses API (strcpy, strncpy, etc.) sont sujettes aux erreurs du programmeur et génèrent facilement des failles de sécurité. Les développeurs doivent remplacer ces API par les versions sécurisées. Visual Studio 2005 est fourni avec un outil permettant d’analyser des fichiers binaires qui peuvent automatiquement case activée fichiers objet pour les références à des API non sécurisées. Pour plus d’informations sur la procédure à suivre avec les informations générées avec cet outil, consultez Repousser les attaques contre votre code avec les bibliothèques C et C++ sécurisées visual Studio 2005 de Martyn Lovell. En outre, vous pouvez obtenir le fichier d’en-tête banned.h qui peut vous aider à supprimer des fonctions interdites du code.

Chacune des erreurs répertoriées est non seulement courante, mais elle est facilement corrigeable sans modification significative de la charge de travail de développement, des normes de codage ou des fonctionnalités.

Exemples de code non sécurisé

Voici un exemple simple de tout ce qu’il faut pour permettre à un attaquant d’effectuer une attaque de dépassement de mémoire tampon :

void GetPlayerName(char *pDatafromNet)
{
    char playername[256]; 
    strncpy(playername, pDatafromNet, strlen(pDatafromNet));

    // ...
}

En surface, ce code semble correct : il appelle une fonction sécurisée, après tout. Les données du réseau sont copiées dans une mémoire tampon de 256 octets. La fonction strncpy s’appuie sur la recherche d’un terminateur NULL dans la chaîne source ou est limitée par le nombre de mémoires tampons fourni. Le problème est que la taille de la mémoire tampon est incorrecte. Si les données du réseau ne sont pas validées ou si la taille de la mémoire tampon est incorrecte (comme dans cet exemple), un attaquant peut simplement fournir une mémoire tampon volumineuse pour remplacer les données de la pile, une fois la mémoire tampon terminée, avec toutes les données du paquet réseau. Cela permettrait à l’attaquant d’exécuter du code arbitraire en remplaçant le pointeur d’instruction et en modifiant l’adresse de retour. La leçon la plus simple de cet exemple consiste à ne jamais approuver les entrées tant qu’elles n’ont pas été vérifiées.

Même si les données ne proviennent pas initialement du réseau, il existe toujours un risque potentiel. Le développement de jeux modernes nécessite de nombreuses personnes qui conçoivent, développent et testent la même base de code. Il n’existe aucun moyen de savoir comment la fonction sera appelée à l’avenir. Demandez-vous toujours d’où proviennent les données et ce qu’un attaquant peut contrôler ? Bien que les attaques basées sur le réseau soient les plus courantes, elles ne sont pas les seules méthodes permettant de créer des failles de sécurité. Un attaquant peut-il créer un mod ou modifier un fichier enregistré d’une manière qui ouvre une faille de sécurité ? Qu’en est-il des fichiers image et audio fournis par l’utilisateur ? Des versions malveillantes de ces fichiers peuvent être publiées sur Internet et créer des risques de sécurité dangereux pour vos clients.

En guise de remarque, utilisez strsafe.h ou Safe CRT au lieu de strncpy pour corriger l’exemple. Safe CRT est une révision complète de la sécurité du runtime C et est fourni avec une partie de Visual Studio 2005. Pour plus d’informations sur safe CRT, consultez Améliorations de la sécurité dans le CRT de Michael Howard.

Moyens d’améliorer la sécurité

Il existe plusieurs façons d’améliorer la sécurité dans le cycle de développement. Voici quelques-unes des meilleures façons :

Lecture sur la sécurité

Le livre , Writing Secure Code, Second Edition de Michael Howard et David LeBlanc, fournit une explication détaillée et claire des stratégies et des méthodes de prévention des attaques et d’atténuation des attaques. En commençant par les méthodes de conception de la sécurité dans une version de techniques de sécurisation des applications réseau, le livre couvre tous les aspects dont un développeur de jeux a besoin pour se protéger, ses produits et ses clients contre les attaquants. Le livre peut être utilisé pour inculquer une culture de sécurité dans un studio de développement. Ne vous contentez pas de considérer la sécurité du code comme le problème d’un développeur ou celui d’un testeur. Considérez la sécurité comme une chose que toute l’équipe ( du gestionnaire de programme au concepteur, au développeur en passant par le testeur) doit réfléchir au moment où elle travaille sur un projet. Plus il y a d’yeux qui font partie du processus d’examen, plus il y a de chances d’attraper un trou de sécurité avant la libération.

Vous trouverez du code sécurisé, deuxième édition dans le Microsoft Press Store et des informations de sécurité plus générales sont disponibles dans Fending Off Future Attacks by Reducing Attack Surface de Michael Howard.

Michael Howard, David LeBlanc et John Viega ont écrit un autre livre sur le sujet qui couvre tous les systèmes d’exploitation et langages de programmation courants, intitulé 19 Deadly Sins of Software Security.

Les présentations de sécurité axées sur les jeux sont disponibles sur la page de téléchargement des présentations pour développeurs Microsoft XNA .

Analyse de la modélisation des menaces

Une analyse de modélisation des menaces est un bon moyen d’évaluer la sécurité du système, non pas dans un langage spécifique ou à l’aide d’un outil, mais dans une méthode globale de bout en bout qui peut être effectuée en quelques réunions. Lorsqu’il est implémenté correctement, un modèle de thread peut identifier toutes les forces et faiblesses d’un système, sans ajouter de charge de travail ou de temps de réunion au projet. La méthode de modélisation des menaces met également l’accent sur l’idée d’évaluer la sécurité du système avant et pendant le processus de développement pour garantir qu’une évaluation complète est effectuée tout en se concentrant sur les fonctionnalités les plus risquées. Il peut être considéré comme un profileur pour la sécurité. En n’étant pas basé sur un langage particulier ou en s’appuyant sur un outil spécifique, la modélisation des menaces peut être utilisée dans n’importe quel studio de développement travaillant sur n’importe quel projet dans n’importe quel genre. La modélisation des menaces est également une excellente méthode pour renforcer l’idée que la sécurité est la responsabilité de chacun et non le problème de quelqu’un d’autre.

Lors de la modélisation des menaces, portez une attention particulière aux points suivants :

  • Sources de données UDP
  • Sources de données qui ne nécessitent pas d’authentification
  • Sources de données fréquemment et normalement sondées dans le cadre de la collecte d’informations à grande échelle
  • Toute capacité d’un client à envoyer directement des données à d’autres clients

Ce sont là les domaines qui présentent un bon potentiel de faiblesses en matière de sécurité.

Pour plus d’informations sur la modélisation des menaces, consultez Modélisation des menaces sur le Centre de développement de sécurité MSDN et dans le livre Threat Modeling de Frank Swiderski et Window Snyder.

Prévention de l’exécution des données (/NX)

La prévention de l’exécution des données (DEP) est un outil récent d’atténuation de plusieurs attaques. Si vous incluez le commutateur /NX dans la commande de génération, Visual Studio marque les pages mémoire avec des indicateurs qui indiquent si le code a le droit d’exécuter ou non. Tout programme qui tente de s’exécuter dans une page mémoire non marquée avec l’autorisation EXECUTE entraîne l’arrêt forcé du programme. La prévention est appliquée au niveau du processeur et aura un impact sur les développeurs qui utilisent du code à modification automatique ou des compilateurs de langage JIT natifs. Actuellement, seuls les processeurs AMD Athlon64 et Opteron et Itanium d’Intel et les derniers processeurs Pentium 4 prennent en charge la prévention de l’exécution, mais on s’attend à ce que tous les processeurs 32 bits et 64 bits prennent en charge la prévention de l’exécution à l’avenir. (Un schéma de protection contre la copie utilisé par un développeur peut être affecté par la prévention de l’exécution, mais Microsoft a travaillé avec les fournisseurs de protection contre la copie pour réduire l’impact.) Il est recommandé d’utiliser DEP.

Pour plus d’informations sur DEP, consultez Prévention de l’exécution des données.

La vérification de sécurité de la mémoire tampon (/GS) et l’image comporte des gestionnaires d’exceptions fiables (/SAFESEH)

La vérification de la sécurité de la mémoire tampon, spécifiée par l’indicateur du compilateur /GS, et l’image a des gestionnaires d’exceptions sécurisées, spécifiés par l’indicateur de l’éditeur de liens /SAFESEH (implémenté pour la première fois dans Visual Studio .NET 2003), peuvent faciliter un peu la sécurisation du code par le développeur.

L’utilisation de l’indicateur /GS amène le compilateur à construire un case activée pour certaines formes de dépassements de mémoire tampon basés sur la pile qui peuvent être exploités pour remplacer l’adresse de retour d’une fonction. L’utilisation de /GS ne détecte pas chaque dépassement potentiel de mémoire tampon et ne doit pas être considérée comme un fourre-tout, mais comme une bonne technologie de défense en profondeur.

L’utilisation de l’indicateur /SAFESEH indique à l’éditeur de liens de générer uniquement un exécutable ou une DLL s’il peut également générer une table des gestionnaires d’exceptions approuvés de l’exécutable ou de la DLL. Safe Structured Exception Handling (SafeSEH) élimine la gestion des exceptions en tant que cible des attaques de dépassement de mémoire tampon en garantissant que, avant qu’une exception ne soit distribuée, le gestionnaire d’exceptions est inscrit dans la table de fonctions située dans le fichier image. Ces avantages de protection sont activés avec Windows XP SP2, Windows Server 2003, Windows Vista et Windows 7. De plus, pour que /SAFESEH fonctionne correctement, il doit être utilisé dans une méthode tout ou rien. Toutes les bibliothèques contenant du code lié à un exécutable ou à une DLL doivent être compilées avec /SAFESEH , sinon la table ne sera pas générée.

Vous trouverez plus d’informations sur la vérification de sécurité de la mémoire tampon (/GS) et l’image avec des gestionnaires d’exceptions fiables (/SAFESEH) dans MSDN.

Consultez également des informations sur l’indicateur /SDL de Microsoft Visual Studio 2012 et les améliorations apportées par Visual Studio 2012 à l’indicateur /GS.

PREfast

PREfast est un outil gratuit proposé par Microsoft qui analyse les chemins d’exécution en C ou C++ compilé pour aider à trouver les bogues d’exécution. PREfast fonctionne en travaillant sur tous les chemins d’exécution dans toutes les fonctions et en évaluant chaque chemin d’accès pour les problèmes. Utilisé à l’origine pour développer des pilotes et d’autres codes de noyau, cet outil peut aider les développeurs de jeux à gagner du temps en éliminant certains bogues difficiles à trouver ou ignorés par le compilateur. L’utilisation de PREfast est un excellent moyen de réduire la charge de travail et de concentrer les efforts de l’équipe de développement et de l’équipe de test. PREfast est disponible dans Visual Studio Team Suite et Visual Studio Team Edition for Software Developers en tant qu’analyse du code, activé par le commutateur du compilateur /analyze. (Cette option est également disponible dans la version gratuite du compilateur fourni avec le Kit de développement logiciel Windows.)

Notes

Visual Studio 2012 prend en charge /analyze dans toutes les éditions. Pour plus d’informations sur la disponibilité de l’analyse du code dans toutes les éditions de Visual Studio, consultez Nouveautés de l’analyse du code.

 

Grâce à l’utilisation de l’annotation d’en-tête (en particulier pour les arguments de pointeur de mémoire tampon), PREfast peut exposer des problèmes supplémentaires, tels que des bogues de remplacement de mémoire, une source courante de plantages et des vulnérabilités de sécurité potentielles. Pour ce faire, utilisez le langage d’annotation standard (SAL), qui est une forme de mark-up pour les prototypes de fonction C/C++ qui fournissent des informations supplémentaires sur la sémantique de l’argument pointeur attendu et la corrélation avec les paramètres de longueur, les tailles de mémoire tampon déclarées, etc. Tous les en-têtes des systèmes d’exploitation Windows sont annotés, et l’ajout d’une marque SAL dans des en-têtes d’API publics dans vos propres bibliothèques permet à PREfast d’effectuer des vérifications plus détaillées et plus agressives dans votre code client pour de telles API. Pour une présentation de SAL et des liens vers plus d’informations, consultez l’entrée de blog de Michael Howard, « A Brief Introduction to the Standard Annotation Language (SAL) ».

Vérificateur d’applications Windows

Le vérificateur d’applications Windows, ou AppVerifier, peut aider les testeurs en fournissant plusieurs fonctions dans un seul outil. AppVerifier est un outil qui a été développé pour rendre les erreurs de programmation courantes plus testables. AppVerifier peut case activée paramètres passés aux appels d’API, injecter des entrées erronées pour case activée capacité de gestion des erreurs et consigner les modifications apportées au Registre et au système de fichiers. AppVerifier peut également détecter les dépassements de mémoire tampon dans le tas, case activée qu’une liste de Access Control (ACL) a été correctement définie et appliquer l’utilisation sécurisée des API de socket. Bien qu’il ne soit pas exhaustif, AppVerifier peut être un outil dans la boîte à outils du testeur pour aider un studio de développement à publier un produit de qualité.

Pour plus d’informations sur Application Verifier, consultez Application Verifier et Using Application Verifier within your Software Development Lifecycle on MSDN.

Fuzz Testing

Le test Fuzz est une méthode de test semi-automatisée qui peut améliorer les méthodologies de test actuelles. L’idée centrale derrière le test fuzz est d’effectuer une évaluation complète de toutes les entrées en entrant des données aléatoires pour voir ce qui se casse; cela inclut toutes les données réseau, les mods et les jeux enregistrés, etc. Les tests fuzz sont assez faciles à faire. Modifiez simplement des fichiers ou des données réseau bien formés en insérant des octets aléatoires, en retournant des octets adjacents ou en annulant des valeurs numériques. 0xff, 0xffff, 0xffffffff, 0x00, 0x0000, 0x00000000 et 0x80000000 sont des valeurs qui permettent d’exposer les trous de sécurité lors des tests de fuzz. Vous pouvez observer les combinaisons d’interactions résultantes à l’aide d’AppVerifier. Bien que le fuzzing ne soit pas exhaustif, il est facile à implémenter et à automatiser, et il peut intercepter les bogues les plus insaisissables et imprévisibles.

Pour plus d’informations sur les tests fuzz, consultez la présentation gamefest 2007Étapes pratiques dans la sécurité du jeu.

Signature Authenticode

Authenticode est une méthode qui permet de s’assurer que les fichiers exécutables, les fichiers DLL et les packages du programme d’installation Windows (.msi fichiers) que l’utilisateur reçoit ne sont pas différents de ce qu’un développeur a publié. En utilisant une combinaison de principes de chiffrement, d’entités approuvées et de normes du secteur, Authenticode vérifie l’intégrité du contenu exécutable. Microsoft fournit une API de chiffrement, CryptoAPI, qui peut être utilisée pour détecter automatiquement la falsification du code signé. Si une fuite de sécurité se produit après une mise en production, un certificat peut être révoqué et tout le code signé avec ce certificat cessera de s’authentifier. La révocation d’un certificat révoque la validation de tous les titres signés avec ce certificat. Windows a été conçu pour fonctionner avec la signature Authenticode et avertit un utilisateur du code non signé, dans des situations spécifiques, qui pourrait exposer le PC d’un utilisateur à une attaque.

Authenticode ne doit pas être considéré comme une méthode d’élimination des problèmes de sécurité, mais comme une méthode de détection de falsification après la publication d’un exécutable. Un exécutable ou une DLL qui contient un problème de sécurité exploitable peut être signé et vérifié à l’aide d’Authenticode, mais il introduit toujours le problème de sécurité dans le nouveau système. Ce n’est qu’après la vérification de la sécurité d’un produit ou d’une mise à jour que le code doit être signé pour garantir aux utilisateurs qu’ils disposent d’une version qui n’a pas été falsifiée.

Même si un développeur estime qu’il n’y a aucune menace de modification de ses versions, d’autres technologies et services s’appuient sur Authenticode. La signature de code est facile à intégrer et à automatiser ; il n’y a aucune raison pour les développeurs de ne pas faire signer leurs versions.

Pour plus d’informations sur la signature Authenticode, consultez Signature Authenticode pour les développeurs de jeux.

Réduire les privilèges

En général, les processus doivent s’exécuter avec l’ensemble minimal de privilèges requis pour fonctionner. Sur Windows Vista et Windows 7, cela s’effectue à l’aide du contrôle de compte d’utilisateur, ce qui permet au jeu de s’exécuter en tant qu’utilisateur standard plutôt qu’en tant qu’administrateur. Pour Windows XP, les jeux s’exécutent généralement toujours en tant qu’administrateur. Même sur Windows Vista et Windows 7, il est parfois nécessaire d’élever au niveau des droits d’administrateur complets pour certaines opérations spécifiques.

Dans les cas où le processus s’exécute avec des droits d’administration complets, en général, seuls quelques droits au-delà de ceux d’un utilisateur standard sont réellement requis. L’accès administratif comprend de nombreux droits qui ne sont pas requis par le code légitime, mais qui peuvent être utilisés par un attaquant, en raison d’une certaine faiblesse du processus. Il s’agit notamment des SE_TAKE_OWNERSHIP, SE_DEBUG, SE_CREATE_TOKEN, SE_ASSIGNPRIMARYTOKEN, SE_TCB, SE_SECURITY, SE_SECURITY, SE_LOAD_DRIVER, SE_SYSTEMTIME, SE_BACKUP, SE_RESTORE, SE_SHUTDOWN et SE_AUDIT (voir Constantes Priviledge).

Bien qu’un processus ne puisse pas obtenir plus de droits une fois démarré, il peut facilement abandonner des droits. Au démarrage, le processus peut utiliser immédiatement les API Win32 pour supprimer les droits dont il n’a pas besoin.

Utiliser les fonctionnalités Sécurité Windows

Windows Vista et Windows 7 incluent un certain nombre de nouvelles fonctionnalités qui améliorent la sécurité du code. Le contrôle de compte d’utilisateur est certainement le plus important à comprendre et à adopter, mais il existe également d’autres fonctionnalités. Outre les technologies Windows XP SP2, telles que le Pare-feu Windows, la prévention de l’exécution des données, la vérification de la sécurité de la mémoire tampon et les gestionnaires d’exceptions sécurisées qui sont également disponibles sur Windows Vista et Windows 7, il existe trois fonctionnalités de sécurité plus récentes à prendre en compte :

  • Fonctionnalité de randomisation de disposition de l’espace d’adressage. Pour cela, vous pouvez établir une liaison avec l’option /DYNAMICBASE sur Visual Studio 2005 Service Pack 1 ou Visual Studio 2008. Cela amène le système à aléatoirer les positions de nombreuses DLL système clés dans votre espace de processus, ce qui rend beaucoup plus difficile l’écriture de programmes d’attaque exploitables qui se propagent largement sur Internet. Cet indicateur d’éditeur de liens est ignoré par Windows XP et les versions antérieures de Windows.
  • L’altération du tas peut entraîner une classe entière d’exploits de sécurité. Par conséquent, le système de mémoire de Windows Vista et de Windows 7 prend désormais en charge un mode qui met fin au processus si une altération du tas est détectée. L’appel de HeapSetInformation avec HeapEnableTermianteOnCorruption va accepter ce comportement. Cet appel échoue sur Windows XP et une version antérieure de Windows.
  • Lors de l’écriture de services, ils peuvent être configurés à l’aide d’une nouvelle fonctionnalité pour spécifier les privilèges réellement requis, ainsi que pour limiter l’accès aux ressources à un SID spécifique. Cela s’effectue via ChangeSeviceConfig2, à l’aide de SERVICE_CONFIG_REQUIRED_PRIVILEGES_INFO et de SERVICE_CONFIG_SERVICE_SID_INFO.

Récapitulatif

Le développement d’un jeu pour la place de marché actuelle et future est coûteux et prend du temps. La publication d’un jeu avec des problèmes de sécurité coûtera en fin de compte plus d’argent et de temps pour corriger correctement. Il est donc dans l’intérêt de tous les développeurs de jeux d’intégrer des outils et des techniques pour atténuer les attaques de sécurité avant la publication.

Les informations contenues dans cet article ne sont qu’une introduction à ce qu’un studio de développement peut faire pour s’aider lui-même et ses clients. Vous trouverez plus d’informations sur les pratiques de sécurité générales et les informations de sécurité dans le Centre de développement sécurité Microsoft.