Bac à sable de sécurité du Webplayer

Dans Unity 3.0, le webplayer implémente un modèle de sécurité très similaire à celui utilisé par Adobe Flash player™. Ces restrictions de sécurité s’appliquent uniquement au webplayer et à l’éditeur lorsque la cible de génération active est WebPlayer. Le modèle de sécurité comporte plusieurs parties:

  • Restrictions d’accès aux données sur un domaine autre que celui qui héberge votre.fichier unity3d.
  • Quelques limitations sur l’utilisation des sockets.
  • Interdire l’invocation de toute méthode que nous jugions interdite. (des choses comme le fichier.Supprimer, etc.).
  • Interdire l’utilisation du système.Réflexion.* pour appeler des méthodes privées / internes dans les classes que vous n’avez pas écrites vous-même.

Actuellement, seules les deux premières parties du modèle de sécurité sont émulées dans l’Éditeur.

La fonctionnalité de mise en réseau muti-player intégrée de Unity (classes UnityEngine.Network, UnityEngine.NetworkView, etc.) n’est pas affectée.

Ce document décrit comment s’assurer que votre contenu continue de fonctionner avec la version 3.0 du webplayer Unity.

  • Consultez la référence de l’API Unity pour plus d’informations sur la classe WWW.
  • Voir la référence de l’API .NET pour plus d’informations sur la classe de socket .NET.

La classe WWW et les sockets utilisent le même schéma de stratégie mais en plus ce sont des systèmes complètement séparés. La stratégie WWW définit uniquement les autorisations sur le service Web où la stratégie est hébergée, mais les stratégies de socket s’appliquent à toutes les connexions de socket TCP/UDP.

L’éditeur Unity est livré avec une fonctionnalité « Émuler la sécurité Web », qui impose le modèle de sécurité du webplayer.Cela permet de détecter facilement les problèmes dans le confort de l’éditeur. Vous pouvez trouver ce paramètre Dansedit-> Paramètres du projet – > Éditeur. Voir aussi les paramètres de l’éditeur.

Le webplayer Unity s’attend à ce qu’un fichier de stratégie http servi nommé crossdomain.xml soit disponible sur le domaine auquel vous souhaitez accéder avec la classe WWW (bien que cela ne soit pas nécessaire s’il s’agit du même domaine qui héberge le fichier unity3d).

Par exemple, imaginez un jeu tetris, hébergé à l’url suivante:

http://gamecompany.com/games/tetris.unity3d

doit accéder à une liste de meilleurs scores à partir de l’url suivante:

http://highscoreprovider.net/gethighscore.php

Dans ce cas, vous devrez placer un fichier crossdomain.xml à la racine du fichier highscoreprovider.net domaine comme celui-ci: http://highscoreprovider.net/crossdomain.xml

Le contenu du fichier crossdomain.xml est au format utilisé par le lecteur Flash. Il est très probable que vous trouverez le fichier crossdomain.xml déjà en place. La stratégie dans le fichier ressemble à ceci:

<?xml version="1.0"?><cross-domain-policy><allow-access-from domain="*"/></cross-domain-policy>

Lorsque ce fichier est placé à http://highscoreprovider.net/crossdomain.xml, le propriétaire de ce domaine déclare que le contenu du serveur Web peut être consulté par n’importe quel lecteur Web provenant de n’importe quel domaine.

Le lecteur Web Unity ne prend pas en charge les balises <allow-http-request-headers-from domain> et <site-control permitted-cross-domain-policies>. Notez que crossdomain.xml doit être un fichier ASCII.

Débogage

La définition d’une variable d’environnement ENABLE_CROSSDOMAIN_LOGGING à 1 entraînera la génération de messages de console lorsque l’exécution Unity récupère et décode le fichier crossdomain.xml. Sur un Mac, vous pouvez définir des variables d’environnement globales en /etc/launchd.conf. Sur un PC, utilisez le Panneau de configuration – > Système et Sécurité – > Système – > Paramètres système avancés – > Variables d’environnement

Voici un exemple de sortie avec ce jeu de variables d’environnement, lorsque le webplayer tente de récupérer une image à partir d’un serveur distant:

Determining crossdomain.xml location for request: http://www.remoteserver.com/image.jpgAbout to parse url: http://www.remoteserver.com/image.jpgDetermining crossdomain.xml location for request: http://www.remoteserver.com/image.jpgAbout to parse url: http://www.remoteserver.com/crossdomain.xmlAbout to parse url: http://www.remoteserver.com/image.jpgDetermining crossdomain.xml location for request: http://www.remoteserver.com/image.jpgDownload had OK statuscodeReceived the following crossdomain.xml--------------------------------------<?xml version="1.0"?><cross-domain-policy><allow-access-from domain="*"/></cross-domain-policy>----------------------received policyParsing: cross-domain-policycross-domain-policyParsing: allow-access-fromallow-access-from domain: *done parsing policycrossdomain.xml was succesfully parsedAbout to parse url: http://www.remoteserver.com/image.jpgChecking if http://www.remoteserver.com/image.jpg is a valid domainChecking request-host: www.remoteserver.com against valid domain: *All requirements met, the request is approved

Lors de l’exécution dans l’Éditeur, ces messages sont écrits dans l’Éditeur.journal. Tenter de lire un fichier crossdomain.xml incorrectement stocké sous la forme utf16 avec un BOM entraînera un échec de l’analyse xml:

BuildFlashPolicy caught an exception while parsing http://www.remoteserver.com/crossdomain.xml: Expected element

En effet, le BOM n’est pas attendu. L’utilisation d’un fichier utf16 non pris en charge sans BOM entraînera:

BuildFlashPolicy caught an exception while parsing http://www.remoteserver.com/crossdomain.xml: Policy can't be constructed from empty stream.

En effet, le premier octet du fichier est nul, ce qui fait penser à l’analyseur qu’il a atteint la fin du fichier. Crossdomain.xml doit être un fichier ASCII.

Implications pour l’utilisation des Sockets :

Un lecteur Web Unity a besoin d’une stratégie de socket servi pour se connecter à un hôte particulier. Cette stratégie est hébergée par défaut par l’hôte cible sur le port 843, mais elle peut également être hébergée sur d’autres ports. La différence fonctionnelle avec un port non par défaut est qu’il doit être récupéré manuellement avec la sécurité.Appel d’API PrefetchSocketPolicy() et s’il est hébergé sur un port supérieur à 1024, la stratégie ne peut donner accès qu’à d’autres ports supérieurs à 1024.

Lorsque vous utilisez le port par défaut, cela fonctionne comme suit: Un lecteur web Unity essaie d’établir une connexion de socket TCP à un hôte, il vérifie d’abord que le serveur hôte acceptera le connection.It pour ce faire, ouvrez un socket TCP sur le port 843, émet une requête et s’attend à recevoir une stratégie de socket sur la nouvelle connexion. Le lecteur Web Unity vérifie ensuite que la stratégie de l’hôte permet à la connexion d’aller de l’avant et qu’elle se déroulera sans erreur si c’est le cas. Ce processus se déroule de manière transparente au code de l’utilisateur, qui n’a pas besoin d’être modifié pour utiliser ce modèle de sécurité. Un exemple de stratégie de socket ressemble à ceci:

<?xml version="1.0"?><cross-domain-policy> <allow-access-from domain="*" to-ports="1200-1220"/> </cross-domain-policy>"

Cette politique dit effectivement que « Le contenu de n’importe quel domaine est libre d’établir des connexions de socket aux ports 1200-1220 ». Le webplayer Unity respectera cela et rejettera toute tentative de connexion socket utilisant un port en dehors de cette plage (une exception SecurityException sera levée).

Lors de l’utilisation de connexions UDP, la stratégie peut également être récupérée automatiquement lorsqu’elle doit être appliquée de la même manière qu’avec TCP. La différence est que la récupération automatique avec TCP se produit lorsque vous vous connectez à quelque chose (vous permet de vous connecter à un serveur), mais avec UDP, car il est sans connexion, cela se produit également lorsque vous appelez un point API qui envoie ou reçoit des données (vous permet d’envoyer / recevoir du trafic vers / depuis un serveur).

Le format utilisé pour la stratégie de socket est le même que celui utilisé par le lecteur Flash, sauf que certaines balises ne sont pas prises en charge. Le lecteur web Unity ne prend en charge que « * » comme valeur valide pour le paramètre de domaine et le paramètre « to-ports » est obligatoire.

<?xml version="1.0" encoding="ISO-8859-1"?><!ELEMENT cross-domain-policy (allow-access-from*)><!ELEMENT allow-access-from EMPTY><!ATTLIST allow-access-from domain CDATA #REQUIRED><!ATTLIST allow-access-from to-ports CDATA #REQUIRED>

La stratégie de socket s’applique aux types de connexion TCP et UDP, de sorte que le trafic UDP et TCP peut être contrôlé par un seul serveur de stratégie.

Pour votre commodité, nous fournissons un petit programme qui écoute simplement sur le port 843; lorsqu’il reçoit une chaîne de requête sur une connexion, il répondra avec une politique de socket valide.Le code du serveur se trouve dans le dossier d’installation de Unity, dans Data/Tools/SocketPolicyServer sous Windows ou /Unity.app/Contents/Tools/SocketPolicyServer sur OS X. Notez que l’exécutable pré-construit peut être exécuté sur Mac car il s’agit d’un exécutable Mono. Tapez simplement « mono sockpol.exe » pour l’exécuter. Notez que cet exemple de code montre le comportement correct d’un serveur de stratégie de socket. Plus précisément, le serveur s’attend à recevoir une chaîne à terminaison zéro contenant < policy-file-request/>. Il n’envoie au client le document xml de stratégie de socket que lorsque cette chaîne (et exactement cette chaîne) a été reçue. De plus, il est nécessaire que l’en-tête xml et le corps xml soient envoyés avec une seule écriture de socket. Le fractionnement de l’en-tête et du corps en opérations d’écriture de socket distinctes peut entraîner des exceptions de sécurité en raison de la réception d’une stratégie incomplète par Unity. Si vous rencontrez des problèmes avec votre propre serveur, veuillez envisager d’utiliser l’exemple que nous fournissons. Cela devrait vous aider à diagnostiquer si vous avez des problèmes de serveur ou de réseau.

Les bibliothèques de mise en réseau tierces, couramment utilisées pour la mise en réseau de jeux multijoueurs, devraient pouvoir répondre à ces exigences tant qu’elles ne dépendent pas de la fonctionnalité peer 2 peer (voir ci-dessous) mais utilisent des serveurs dédiés. Ceux-ci sortent parfois même de la boîte avec la prise en charge des politiques d’hébergement.

Remarque: Alors que les fichiers de stratégie crossdomain.xml et de socket sont tous deux des documents XML et sont globalement similaires, la façon dont ces documents sont servis est très différente. Crossdomain.xml (appliqué aux requêtes http) est récupéré à l’aide de http sur le port 80, où -as la stratégie de socket est récupérée à partir du port 843 à l’aide d’un serveur trivial qui implémente la <policy-file-request/>. Vous ne pouvez pas utiliser un serveur http pour émettre le fichier de stratégie de socket, ni configurer un serveur qui envoie simplement le fichier de stratégie de socket en réponse à une connexion de socket sur le port 843. Notez également que chaque serveur auquel vous vous connectez nécessite son propre serveur de stratégie de socket.

Débogage

Vous pouvez utiliser telnet pour vous connecter au serveur de stratégie de socket. Un exemple de session est illustré ci-dessous:

host$ telnet localhost 843Trying 127.0.0.1...Connected to localhost.Escape character is '^]'.<policy-file-request/><?xml version='1.0'?><cross-domain-policy> <allow-access-from domain="*" to-ports="*" /></cross-domain-policy>Connection closed by foreign host.host$

Dans cet exemple de session, telnet est utilisé pour se connecter à l’hôte local sur le port 843. Telnet répond avec les trois premières lignes, puis attend que l’utilisateur entre quelque chose. L’utilisateur a entré la chaîne de requête de stratégie < policy-file-request/>, que le serveur de stratégie de socket reçoit et répond avec la stratégie de socket. Le serveur se déconnecte alors, ce qui oblige telnet à signaler que la connexion a été fermée.

Sockets d’écoute

Vous ne pouvez pas créer de sockets d’écoute dans le webplayer, il ne peut pas agir comme un serveur. Par conséquent, les webplayers ne peuvent pas communiquer directement entre eux (peer 2 peer). Lorsque vous utilisez des sockets TCP, vous ne pouvez vous connecter à des points de terminaison distants que si cela est autorisé via le système de stratégie de socket. Pour UDP, cela fonctionne de la même manière, mais le concept est un peu différent car il s’agit d’un protocole sans connexion, vous n’avez pas besoin de vous connecter / écouter pour envoyer / recevoir des paquets. Cela fonctionne en imposant que vous ne pouvez recevoir des paquets d’un serveur que s’il a répondu en premier avec une stratégie valide avec la balise allow-access-from domain.

Tout cela est tellement ennuyeux, pourquoi tout cela existe-t-il?

Les fonctions de sécurité socket et WWW existent pour protéger les personnes qui installent le lecteur Web Unity. Sans ces restrictions, une attaque telle que la suivante serait possible:

  • Bob travaille à la maison blanche.
  • Frank est mauvais. Il écrit un jeu web unity qui prétend être un jeu, mais en arrière-plan fait une demande WWW à http://internal.whitehouse.gov/LocationOfNuclearBombs.pdf. interne.maison blanche.gov est un serveur qui n’est pas accessible depuis Internet, mais qui est accessible depuis le poste de travail de Bob car il travaille à la maison blanche.
  • Frank envoie ces octets pdf à http://frank.com/secretDataUploader.php
  • Frank place ce jeu sur http://www.frank.com/coolgame.unity3d
  • Frank convainc en quelque sorte Bob de jouer au jeu.
  • Bob joue le jeu.
  • Game télécharge silencieusement le document secret et l’envoie à Frank.

Avec les fonctionnalités de sécurité WWW et socket, cette attaque échouera, car avant de télécharger le pdf, unity vérifie http://internal.whitehouse.gov/crossdomain.xml, avec l’intention de demander à ce serveur:  » les données que vous avez sur votre serveur sont-elles disponibles pour un usage public ? ». Placer un domaine croisé.xml sur un serveur Web peut être considéré comme la réponse à cette question. Dans le cas de cet exemple, l’opérateur du système de internal.whitehouse.gov ne place pas de domaine croisé.xml sur son serveur, ce qui conduira Unity à ne pas télécharger le pdf.

Malheureusement, afin de protéger les personnes qui installent le lecteur Web Unity, les personnes qui se développent dans Unity doivent prendre en compte ces mesures de sécurité lors du développement de contenu. Les mêmes restrictions sont présentes dans toutes les principales technologies de plugin. (Flash, Silverlight, Shockwave)

Exceptions

Afin de trouver le bon équilibre entre la protection des utilisateurs de lecteurs Web et la facilité de vie des développeurs de contenu, nous avons mis en place une exception au mécanisme de sécurité décrit ci-dessus:

Vous êtes autorisé à télécharger des images à partir de serveurs qui n’ont pas de domaine croisé.fichier xml. Cependant, la seule chose que vous êtes autorisé à faire avec ces images est de les utiliser comme textures dans votre scène. Vous n’êtes pas autorisé à utiliser GetPixel() dessus. Vous n’êtes pas non plus autorisé à lire à l’écran. Les deux tentatives entraîneront le lancement d’une exception SecurityException:

SecurityException: No read access to the texture data: at (wrapper managed-to-native) UnityEngine.Texture2D:GetPixel (int,int)

Le raisonnement est le suivant: il est acceptable de télécharger l’image, tant que le développeur de contenu n’y a pas accès. Vous pouvez donc l’afficher à l’utilisateur, mais vous ne pouvez pas renvoyer les octets de l’image à un autre serveur. Si vous avez besoin d’accéder aux données de pixels, placez un fichier crossdomain.xml sur le serveur à partir duquel les images sont extraites.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée.