In Unity 3.0, il webplayer implementa un modello di sicurezza molto simile a quello utilizzato da Adobe Flash player™. Queste restrizioni di sicurezza si applicano solo al webplayer e all’editor quando la destinazione di compilazione attiva è WebPlayer. Il modello di sicurezza ha diverse parti:
- Restrizioni sull’accesso ai dati su un dominio diverso da quello che ospita il tuo .file unity3d.
- Alcune limitazioni sull’utilizzo dei socket.
- Non consentire l’invocazione di qualsiasi metodo ritenuto off limits. (cose come File.Elimina, ecc.).
- Non consentire l’utilizzo del sistema.Riflessione.* per chiamare metodi privati / interni nelle classi non hai scritto te stesso.
Attualmente solo le prime due parti del modello di sicurezza sono emulate nell’Editor.
La funzionalità di rete muti-player integrata di Unity (UnityEngine.Network
, UnityEngine.NetworkView
classi ecc.) non è interessata.
Questo documento descrive come assicurarsi che il contenuto continui a funzionare con la versione 3.0 di Unity webplayer.
- Vedere il riferimento API Unity per informazioni sulla classe WWW.
- Vedere il riferimento API. NET per informazioni sulla classe Socket. NET.
La classe WWW e i socket utilizzano lo stesso schema di policy ma sono sistemi completamente separati. Il criterio WWW definisce solo le autorizzazioni sul servizio Web in cui è ospitato il criterio, ma i criteri socket si applicano a tutte le connessioni socket TCP / UDP.
L’editor di Unity è dotato di una funzione “Emula sicurezza Web”, che impone il modello di sicurezza del webplayer.Questo rende facile rilevare i problemi dalla comodità dell’editor. È possibile trovare questa impostazione inEdit->Impostazioni progetto – > Editor. Vedere anche le impostazioni dell’editor.
Il webplayer di Unity prevede che un file di policy servito http denominato crossdomain.xml
sia disponibile sul dominio a cui si desidera accedere con la classe WWW,(anche se questo non è necessario se è lo stesso dominio che ospita il file unity3d).
Ad esempio, immagina un gioco tetris, ospitato al seguente url:
http://gamecompany.com/games/tetris.unity3d
deve accedere a un elenco di punteggi migliori dal seguente URL:
http://highscoreprovider.net/gethighscore.php
In questo caso, è necessario posizionare un file crossdomain.xml
alla radice del highscoreprovider.net dominio come questo: http://highscoreprovider.net/crossdomain.xml
Il contenuto del file crossdomain.xml
è nel formato utilizzato da Flash player. È molto probabile che troverai il file crossdomain.xml
già in atto. La politica nel file assomiglia a questa:
<?xml version="1.0"?><cross-domain-policy><allow-access-from domain="*"/></cross-domain-policy>
Quando questo file viene inserito in http://highscoreprovider.net/crossdomain.xml, il proprietario di quel dominio dichiara che il contenuto del server Web può essere accessibile da qualsiasi giocatore Web proveniente da qualsiasi dominio.
Il webplayer Unity non supporta i tag < allow-http-request-headers-from domain>e < site-control permissed-cross-domain-policies>. Si noti che crossdomain.xml
dovrebbe essere un file ASCII.
Debug
L’impostazione di una variabile di ambiente ENABLE_CROSSDOMAIN_LOGGING
su 1
causerà la generazione di messaggi della console mentre il runtime Unity recupera e decodifica il file crossdomain.xml
. Su un Mac è possibile impostare variabili di ambiente globali in /etc/launchd.conf
. Su un PC, utilizzare il Pannello di Controllo->Sistema E Sicurezza->Sistema>impostazioni di sistema Avanzate->Variabili d’Ambiente…
Ecco un esempio di output con questa variabile di ambiente impostata, quando il webplayer i tentativi di recupero di un’immagine da un server remoto:
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
Quando si esegue l’Editor di questi messaggi vengono scritti per l’Editor.log. Il tentativo di leggere un file crossdomain.xml
memorizzato in modo errato come utf16
con un BOM
comporterà un errore nell’analisi dell’xml:
BuildFlashPolicy caught an exception while parsing http://www.remoteserver.com/crossdomain.xml: Expected element
Questo perché BOM
non è previsto. L’utilizzo di un file utf16
non supportato con no BOM
comporterà:
BuildFlashPolicy caught an exception while parsing http://www.remoteserver.com/crossdomain.xml: Policy can't be constructed from empty stream.
Questo perché il primo byte nel file è zero, il che fa sì che il parser pensi di aver raggiunto la fine del file. Crossdomain.xml
deve essere un file ASCII.
Implicazioni per l’uso di socket:
Un webplayer Unity ha bisogno di una politica servita da socket per connettersi a un determinato host. Questo criterio è di default ospitato dall’host di destinazione sulla porta 843, ma può essere ospitato anche su altre porte. La differenza funzionale con una porta non predefinita è che deve essere recuperata manualmente con Sicurezza.PrefetchSocketPolicy () chiamata API e se è ospitato su una porta superiore a 1024 la politica può dare accesso solo ad altre porte superiori a 1024.
Quando si utilizza la porta predefinita funziona in questo modo: un webplayer Unity tenta di creare una connessione socket TCP a un host, prima controlla che il server host accetterà connection.It lo fa aprendo un socket TCP sulla porta 843, emette una richiesta e si aspetta di ricevere una politica di socket sulla nuova connessione. Il webplayer Unity controlla quindi che la politica dell’host consenta alla connessione di andare avanti e procederà senza errori in tal caso. Questo processo avviene in modo trasparente al codice dell’utente, che non ha bisogno di essere modificato per utilizzare questo modello di sicurezza. Un esempio di una politica socket simile a questo:
<?xml version="1.0"?><cross-domain-policy> <allow-access-from domain="*" to-ports="1200-1220"/> </cross-domain-policy>"
Questa politica dice in modo efficace “Il contenuto di qualsiasi dominio è libero di effettuare connessioni socket alle porte 1200-1220”. Il webplayer Unity rispetterà questo e respingerà qualsiasi tentativo di connessione socket utilizzando una porta al di fuori di tale intervallo (verrà generata una SecurityException).
Quando si utilizzano connessioni UDP, la politica può anche essere recuperata automaticamente quando devono essere applicate in modo simile a TCP. La differenza è che il recupero automatico con TCP avviene quando ci si connette a qualcosa (garantisce che sia consentito connettersi a un server), ma con UDP, poiché è senza connessione, accade anche quando si chiama qualsiasi punto API che invia o riceve dati (assicura che sia consentito inviare/ricevere traffico da/verso un server).
Il formato utilizzato per il criterio socket è lo stesso utilizzato da Flash player, tranne che alcuni tag non sono supportati. Il webplayer Unity supporta solo ” * “come valore valido per l’impostazione del dominio e l’impostazione” to-ports ” è obbligatoria.
<?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>
Il criterio socket si applica sia ai tipi di connessione TCP che UDP in modo che sia il traffico UDP che TCP possano essere controllati da un server di policy.
Per comodità, forniamo un piccolo programma che ascolta semplicemente alla porta 843; quando su una connessione riceve una stringa di richiesta, risponderà con una politica di socket valida.Il codice del server può essere trovato all’interno della cartella di installazione di Unity, in Data/Tools/SocketPolicyServer su Windows o /Unity.app / Contents/Tools / SocketPolicyServer su OS X. Si noti che l’eseguibile pre-costruito può essere eseguito su Mac poiché è un eseguibile Mono. Basta digitare ” mono sockpol.exe ” per eseguirlo. Si noti che questo codice di esempio mostra il comportamento corretto di un server di criteri socket. In particolare, il server si aspetta di ricevere una stringa con terminazione zero che contiene < policy-file-request / >. Invia al client solo il documento xml della politica socket quando questa stringa (ed esattamente questa stringa) è stata ricevuta. Inoltre, è necessario che l’intestazione xml e il corpo xml vengano inviati con una singola scrittura socket. L’interruzione dell’intestazione e del corpo in operazioni di scrittura socket separate può causare eccezioni di sicurezza a causa della ricezione di Unity di un criterio incompleto. Se si verificano problemi con il proprio server si prega di considerare l’esempio che forniamo. Questo dovrebbe aiutare a diagnosticare se si dispone di server o problemi di rete.
Le librerie di rete di terze parti, comunemente utilizzate per la rete di giochi multiplayer, dovrebbero essere in grado di lavorare con questi requisiti purché non dipendano dalla funzionalità peer 2 peer (vedi sotto) ma utilizzino server dedicati. Questi a volte anche venire fuori dalla scatola con il supporto per le politiche di hosting.
Nota: Mentre i file crossdomain.xml
e socket policy sono entrambi documenti xml e sono sostanzialmente simili, il modo in cui questi documenti vengono serviti è molto diverso. Crossdomain.xml
(che si applica alle richieste http) viene recuperato utilizzando http sulla porta 80, dove-come la politica del socket viene recuperata dalla porta 843 utilizzando un server banale che implementa la <policy-file-request/>. Non è possibile utilizzare un server http per emettere il file dei criteri socket, né impostare un server che invia semplicemente il file dei criteri socket in risposta a una connessione socket sulla porta 843. Si noti inoltre che ogni server a cui ci si connette richiede il proprio server di criteri socket.
Debug
È possibile utilizzare telnet
per connettersi al server criteri socket. Di seguito viene mostrata una sessione di esempio:
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$
In questa sessione di esempio, telnet viene utilizzato per connettersi al localhost sulla porta 843. Telnet risponde con le prime tre righe e quindi si siede in attesa che l’utente inserisca qualcosa. L’utente ha inserito la stringa di richiesta dei criteri < policy-file-request / >, che il server dei criteri socket riceve e risponde con i criteri socket. Il server quindi si disconnette causando telnet per segnalare che la connessione è stata chiusa.
Socket di ascolto
Non è possibile creare socket di ascolto nel webplayer, non può fungere da server. Pertanto i webplayer non possono comunicare tra loro direttamente (peer 2 peer). Quando si utilizzano socket TCP, è possibile connettersi solo agli endpoint remoti a condizione che sia consentito tramite il sistema di criteri socket. Per UDP funziona allo stesso modo, ma il concetto è un po ‘ diverso in quanto è un protocollo senza connessione, non è necessario connettersi/ascoltare per inviare/ricevere pacchetti. Funziona imponendo che è possibile ricevere pacchetti da un server solo se ha risposto per primo con una politica valida con il tag allow-access-from domain
.
Questo è tutto così fastidioso, perché esiste tutta questa roba?
Le funzionalità di sicurezza socket e WWW esistono per proteggere le persone che installano Unity Web Player. Senza queste restrizioni, un attacco come il seguente sarebbe possibile:
- Bob lavora alla casa bianca.
- Frank è malvagio. Scrive un webgame unity che finge di essere un gioco, ma in background fa una richiesta WWW a http://internal.whitehouse.gov/LocationOfNuclearBombs.pdf. interno.Whitehouse.gov è un server che non è raggiungibile da Internet, ma è raggiungibile dalla workstation di Bob perché lavora alla casa bianca.
- Frank invia quei byte pdf a http://frank.com/secretDataUploader.php
- Frank posiziona questo gioco su http://www.frank.com/coolgame.unity3d
- Frank convince in qualche modo Bob a giocare.
- Bob gioca il gioco.
- Gioco scarica silenziosamente il documento segreto, e lo invia a Frank.
Con le funzionalità di sicurezza WWW e socket, questo attacco fallirà, perché prima di scaricare il pdf, unity controlla http://internal.whitehouse.gov/crossdomain.xml, con l’intento di chiedere a quel server: “i dati che hai sul tuo server sono disponibili per l’uso pubblico?”. Posizionamento di un crossdomain.xml su un server Web può essere visto come la risposta a questa domanda. Nel caso di questo esempio, il gestore del sistema di internal.whitehouse.gov non metterà un crossdomain.xml sul suo server, che porterà Unity a non scaricare il pdf.
Sfortunatamente, per proteggere le persone che installano Unity Web Player, le persone che si sviluppano in Unity devono prendere in considerazione queste misure di sicurezza durante lo sviluppo di contenuti. Le stesse restrizioni sono presenti in tutte le principali tecnologie di plugin. (Flash, Silverlight, Shockwave)
Eccezioni
Al fine di trovare il giusto equilibrio tra la protezione degli utenti Web Player e rendere la vita degli sviluppatori di contenuti facile, abbiamo implementato un’eccezione al meccanismo di sicurezza sopra descritto:
È consentito scaricare immagini da server che non hanno un crossdomain.file xml. Tuttavia, l’unica cosa che puoi fare con queste immagini è usarle come trame nella tua scena. Non è consentito utilizzare GetPixel() su di essi. Inoltre, non è consentito leggere indietro dallo schermo. Entrambi i tentativi si tradurranno in un SecurityException essere gettato:
SecurityException: No read access to the texture data: at (wrapper managed-to-native) UnityEngine.Texture2D:GetPixel (int,int)
Il ragionamento è qui è che va bene scaricare l’immagine, purché lo sviluppatore di contenuti non abbia accesso ad essa. Quindi puoi visualizzarlo all’utente, ma non puoi inviare i byte dell’immagine a un altro server. Se è necessario accedere ai dati dei pixel, posizionare un file crossdomain.xml
sul server da cui vengono recuperate le immagini.