Creación de scripts entre contenido en diferentes dominios

Adobe AIR 1.0 y posterior

Las aplicaciones de AIR tienen privilegios especiales cuando se instalan. Es fundamental que los mismos privilegios no se filtren a otro contenido, incluyendo archivos remotos y archivos locales que no son parte de la aplicación.

Puente de entorno limitado de AIR

Normalmente, el contenido de otros dominios no pueden llamar a scripts en otros dominios. Para proteger las aplicaciones de AIR de filtraciones accidentales de control o información privilegiada, se implementan las siguientes restricciones en el contenido en el entorno limitado de seguridad aplicación (contenido instalado con la aplicación).

  • El código en el entorno limitado de seguridad de la aplicación no se permite en otros entornos limitados llamando al método Security.allowDomain() . Con la llamada a este método desde el entorno limitado de seguridad de la aplicación se emitirá un error.

  • Se impide la importación de contenido que no pertenece a la aplicación en el entorno limitado de la aplicación si se define la propiedad LoaderContext.securityDomain o LoaderContext.applicationDomain .

Aún hay casos donde la aplicación de AIR principal requiere que el contenido de un dominio remoto tenga acceso controlado a los scripts en la aplicación de AIR principal o viceversa. Para lograr esto, el motor de ejecución proporciona un mecanismo de puente de entorno limitado , que actúa como una puerta de enlace entre los dos entornos limitados. Un puente de entorno limitado puede proporcionar interacción explícita entre entornos limitados de seguridad de aplicación y remotos.

El puente de entorno limitado expone dos objetos al que pueden acceder ambos scripts cargados y los que se están cargando:

  • El objeto parentSandboxBridge permite que el contenido que se está cargando exponga las propiedades y funciones a los scripts en el contenido cargado.

  • El objeto childSandboxBridge permite que el contenido cargado exponga las propiedades y funciones a los scripts en el contenido que se está cargando.

Los objetos expuestos a través del puente de entorno limitado se pasan por valor y no por referencia. Todos los datos se serializan. Esto significa que los objetos expuestos por un lado del puente no pueden ser definidos por el otro lado del puente y que los objetos expuestos no tienen tipo. Asimismo, solo se pueden exponer funciones y objetos simples; no se pueden exponer objetos complejos.

Si el contenido secundario intenta definir una propiedad del objeto parentSandboxBridge, el motor de ejecución emite una excepción SecurityError. De igual manera, si el contenido principal intenta definir una propiedad del objeto childSandboxBridge, el motor de ejecución emite una excepción SecurityError.

Ejemplo de puente de entorno limitado (SWF)

Supongamos que una aplicación de almacén de música de AIR quiere permitir que los archivos SWF remotos transmitan el precio de los álbumes, pero no quiere que el archivo SWF remoto divulgue si el precio es un precio de oferta. Para hacer esto, una clase StoreAPI proporciona un método para adquirir el precio, pero oculta el precio de oferta. Una instancia de esta clase StoreAPI se asigna a continuación a la propiedad parentSandboxBridge del objeto LoaderInfo del objeto Loader que carga el SWF remoto.

El siguiente es el código para almacén de música de AIR:

<?xml version="1.0" encoding="utf-8"?> 
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" title="Music Store" creationComplete="initApp()"> 
    <mx:Script> 
        import flash.display.Loader; 
        import flash.net.URLRequest; 
     
        private var child:Loader; 
        private var isSale:Boolean = false; 
         
        private function initApp():void { 
            var request:URLRequest =  
                    new URLRequest("http://[www.yourdomain.com]/PriceQuoter.swf") 
 
            child = new Loader(); 
            child.contentLoaderInfo.parentSandboxBridge = new StoreAPI(this); 
            child.load(request); 
            container.addChild(child); 
        } 
        public function getRegularAlbumPrice():String { 
            return "$11.99"; 
        } 
        public function getSaleAlbumPrice():String { 
            return "$9.99"; 
        } 
        public function getAlbumPrice():String { 
            if(isSale) { 
                return getSaleAlbumPrice(); 
            } 
            else { 
                return getRegularAlbumPrice();     
            } 
        } 
    </mx:Script> 
    <mx:UIComponent id="container" /> 
</mx:WindowedApplication> 

El objeto StoreAPI llama a la aplicación principal para recuperar el precio normal del álbum, pero devuelve “No disponible” cuando se llama al método getSaleAlbumPrice() . El siguiente código define la clase StoreAPI:

public class StoreAPI 
{ 
    private static var musicStore:Object; 
     
    public function StoreAPI(musicStore:Object) 
    { 
        this.musicStore = musicStore; 
    } 
 
    public function getRegularAlbumPrice():String { 
        return musicStore.getRegularAlbumPrice(); 
    } 
     
    public function getSaleAlbumPrice():String { 
        return "Not available"; 
    } 
     
    public function getAlbumPrice():String { 
        return musicStore.getRegularAlbumPrice();     
    } 
}

El siguiente código representa un ejemplo del archivo SWF PriceQuoter que informa sobre el precio de venta pero no puede informar sobre el pecio de oferta:

package 
{ 
    import flash.display.Sprite; 
    import flash.system.Security; 
    import flash.text.*; 
     
    public class PriceQuoter extends Sprite 
    { 
        private var storeRequester:Object; 
         
        public function PriceQuoter() { 
            trace("Initializing child SWF"); 
            trace("Child sandbox: " + Security.sandboxType); 
            storeRequester = loaderInfo.parentSandboxBridge; 
             
            var tf:TextField = new TextField(); 
            tf.autoSize = TextFieldAutoSize.LEFT; 
            addChild(tf); 
             
            tf.appendText("Store price of album is: " + storeRequester.getAlbumPrice()); 
            tf.appendText("\n"); 
            tf.appendText("Sale price of album is: " + storeRequester.getSaleAlbumPrice()); 
        } 
    } 
}

Ejemplo de puente de entorno limitado (HTML)

En el contenido HTML, las propiedades parentSandboxBridge y childSandboxBridge se añaden al objeto window JavaScript de un documento secundario. Para obtener un ejemplo de cómo configurar las funciones del puente en el contenido HTML, consulte Definición de una interfaz de puente de entorno limitado .

Limitación de la exposición de API

Cuando se exponen puentes de entorno limitado, es importante exponer las API de nivel alto que limitan el grado del uso indebido. Tenga en cuenta que el contenido que está llamando a la implementación del puente puede dejar el sistema vulnerable (por ejemplo, a través de una inyección de código). Entonces, por ejemplo, la exposición de un método readFile(path:String) (que lee los contenidos de un archivo arbitrario) a través de un puente es vulnerable a ser utilizado incorrectamente. Sería mejor exponer una API readApplicationSetting() que no usa una ruta y lee un archivo específico. El método más semántico limita el daño que puede hacer una aplicación una vez que parte de la misma está en peligro.