Accessibility

Table of Contents

Creating more secure SWF web applications

Communicating between SWFs and across domains

Related threats: Cross-domain privilege escalation, malicious data injection, unauthorized access to data in transit, insufficient authorization restrictions

Flash Player provides several methods for communication between SWF files depending on the developers needs. Each of the methods includes a cross-domain communication capability. Which method is appropriate depends on the use case scenario and how much trust exists between the two domains.

The solutions can be subdivided into direct communication and communication through a common resource. Direct communication methods require the target SWF file to be loaded by the sender. If a common resource for communicating is created, then loading operations are not needed and communication can occur between multiple SWF files.

Below is a list of the common methods and some things to consider regarding their capability and security.

Direct communication

Import loading via Loaders:

  • Once loaded, the remote SWF can not cross-script with its original domain
  • The remote SWF can cross-script into any SWF in the loading domain.
  • Access is limited to communication between two domains per loader
  • Implemented through a Loader.load() with LoaderContext settings or Loader.loadBytes() methods
  • Available in ActionScript 3.0 / Flash Player 9 and later
  • Requires a HTTP cross-domain policy

Cross-scripting permissions via flash.system.Security.allowDomain():

  • One-way communication for cross-scripting between domains
  • Any SWF file on the remote domain can cross-script into the specific SWF granting access.
  • Access is granted only to the SWF containing the Security.allowDomain() method
  • Both SWF files still maintain access to their original domain
  • SWF files within the same domain can automatically cross-script
  • The Security.allowDomain() method can allow access to multiple remote domains
  • This is an alternative for SWF files that are not import loaded
  • No HTTP cross-domain policy required

SharedEvents:

  • Allows a loaded SWF to propagate event data to the parent and vice-versa
  • Requires knowledge of the communication bridge by both parties
  • Limited event information can be passed between the parent and child
  • Can be used as a communication vector between mutually untrusted parties
  • Used in the Flex "Marshall Plan" project
  • No HTTP cross-domain policy required

Communication through a shared resource

LocalConnection:

  • Multiple domains can be permitted to connect via LocalConnection.allowDomain()
  • Multiple remote SWFs can communicate to the SWF with the LocalConnection
  • LocalConnection limits the exposure of methods to the remote domain
  • Any SWF that is active on the machine can communicate to the LocalConnection.
  • 40K limit on amount of data transmitted in a single send request

Local shared objects:

  • Not reliable because the user can disable access and set storage limitations
  • Data is stored unencrypted on the disk
  • Data is available across multiple sessions
  • Access is subject to the localPath and secure flag settings
  • Only useful for communicating between SWF files within the same domain
  • SWF files need to opt into sharing by using a common, non-default path

JavaScript relaying:

  • May require JavaScript within the hosting HTML page
  • Relaying is through a potentially untrusted third-party
  • Dependent on the allowScriptAccess setting within the HTML
  • Inefficient for large data exchanges
  • Careful coding must be used to prevent cross-site scripting

Loaders

Related threats: Cross-domain privilege escalation, malicious data injection, unauthorized access to data in transit, insufficient authorization restrictions

To learn more about security settings while using the Loader class, see LoaderContext() in the ActionScript 3.0 Language and Components Reference.

You can use the Loader class for import loading or for cross-scripting communication depending on the domains specified within the LoaderContext parameter settings. Two types of domains can be specified when loading content. The first is a security domain which is typically defined by the location where the SWF was loaded. The security domain is used to determine whether the SWF should be import loaded. Each security domain can contain multiple "ApplicationDomains" which define inheritance and access boundaries between classes within the code. ApplicationDomains are only supported in SWF files authored in ActionScript 3.0. Both application and security domains are defined within the Loader's LoaderContext settings.

Be aware of when Flash Player defaults to import loading

Security domains can be assigned when a SWF file is being loaded from another domain. By default in a HTML page, two SWF files loaded independently from different domain names will have different security domains. If the loading SWF file explicitly trusts the remote SWF by incorporating the remote SWF into its code, then the loading SWF can import it directly into its own security domain. This process is called import loading. Import loading allows the developer to load remote SWF files from other domains as though they were loaded from the developer's domain. This should only be considered in situations when you completely trust the content coming from the remote domain. Import loading is the ActionScript 3.0 equivalent of running eval() on someone else's code. If the SWF file remains within its own security domain, then cross-scripting permissions must be employed in order to allow communication which will be discussed later in this section.

There are two ways you can perform import loading in order to load a remote SWF into the current security domain. When Loader.loadBytes() is used to load a SWF, the SWF is loaded into the security domain of the loading SWF by default, if the LoaderContext is set to null. The second method involves specifying in the LoaderContext that the SecurityDomain is the currentDomain. You can only change the security domain of the loaded SWF to the loading SWF file's domain. Additionally, a crossdomain.xml file must exist on the remote server approving the loading of the SWF by the current domain.

The code example below shows an example of using LoaderContext:

// This will result in import loading (the default for Flash Player)
var ldr:Loader = new Loader();
var url:String = "http://www.unknown.example.com/content.swf";
var urlReq:URLRequest = new URLRequest(url);
ldr.loadBytes(urlReq);
 
// This will also result in import loading
var ldr:Loader = new Loader();
var loader_context:LoaderContext = new LoaderContext()
loader_context.securityDomain = SecurityDomain.currentDomain
var url:String = "http://www.unknown.example.com/content.swf";
var urlReq:URLRequest = new URLRequest(url);
ldr.load(urlReq,loader_context);
 
// Load a SWF but leave it in its own security domain
var ldr:Loader = new Loader();
var url:String = "http://www.unknown.example.com/content.swf";
var urlReq:URLRequest = new URLRequest(url);
ldr.load(urlReq);

Import loading can allow a SWF file to talk to the loading SWF file's DOM

When you are loading a remote SWF, consider both the impact of the access that SWF file will have with other SWF components as well as the impact on the web page where it is loaded. If allowScriptAccess is set to Always, then any method of loading a SWF file will allow script access to the hosting web page. If allowScriptAccess is set to sameDomain then import loading the remote SWF grants it access to the hosting web page.

Setting application domains

Application domains define how classes are handled by the interpreter and whether the loaded SWF can access or inherit the loading SWF file's classes. Application domains are for managing cooperating units of ActionScript code and are not intended for security purposes. They can not be applied to SWF files authored in ActionScript 2.0 or ActionScript 1.0. Which option is appropriate will depend on the specific application. Choosing to load the SWF with the default option of being a child of the loader's ApplicationDomain or into the loader's own ApplicationDomain will result in the loaded SWF being able to access or inherit the parent SWF's classes. If the loading SWF has classes that should not be immediately exposed to loaded SWF files, then the developer should load the SWF as a child of the system's ApplicationDomain to ensure it does not inherit the loading SWF file's classes. However, in this usage, the child SWF file may still be able to explicitly retrieve definitions from other ApplicationDomains if it knows their location.

The code example below shows how this is accomplished:

// Create the request and LoaderContext for the application domain
request = new URLRequest(swfLib);
var context:LoaderContext = new LoaderContext();

// Option 1: Loads the SWF as a child of the current domain
context.applicationDomain = new ApplicationDomain(ApplicationDomain.currentDomain)

// Option 2: Sets the application domain to the current domain
context.applicationDomain = ApplicationDomain.currentDomain;

// Option 3: This separates the loader and loadee entirely
context.applicationDomain = new ApplicationDomain(null).

// Option 4: A complex example demonstrating how to load a SWF
// file into a new child of the current domain's parent's parent
Content.applicationDomain = new ApplicationDomain(ApplicationDomain.currentDomain.parentDomain.parentDomain)

// Load the request based on the context setting
loader.load(request, context);

Cross-scripting between domains

Related threats: Cross-domain privilege escalation, malicious data injection, unauthorized access to data in transit, insufficient authorization restrictions

To get more information about topics discussed in this section, see the following sections in the ActionScript 3.0 Language and Components Reference:

If you load two SWF files from the same domain, you have several methods you can use to allow the SWFs to communicate and share data and functions. However, if the two SWF files are loaded from different domains, then they are not allowed to communicate via cross-scripting unless you specifically grant access by specifying system.Security.allowDomain() within the SWF file that will be accessed. The allowDomain setting allows only one-way communication. If the two SWF files need to exchange data in both directions, then both SWF files must contain an allowDomain statement (see Figure 1).

Using security.allowDomain in ActionScript 3.0

Using allowDomain in ActionScript 2.0

Figure 1. Using security.allowDomain in ActionScript 3.0 (top) or allowDomain in ActionScript 2.0 (bottom) to enable communication between SWFs loaded on different domains

When a SWF file loaded over HTTP wants to access data from a SWF file served over HTTPS then special permission must be granted. In these situations you can use, the security.allowInsecureDomain() call. It is highly recommended to avoid these types of scenarios whenever possible. Using this type of communication may potentially allow sensitive data protected by SSL to be leaked into an unprotected environment.

It is also important to note that while Flash Player differentiates between the HTTP and HTTPS protocol, Flash Player does not differentiate based on the port. If a parent SWF loaded over HTTP from www.example.org:80 were to load a child SWF over HTTP from www.example.org:8080, then no security.allowDomain() would be necessary because they would be both served from the same domain using the same protocol. If a SWF loaded via HTTP from www.example.org:8080 were to try and cross-script into a child SWF that was loaded over HTTPS from www2.example.org:8443 and had a security.allowDomain("www.example.org") setting, then the communication would be denied because they would be both loaded via different protocols. The SWF would need a security.allowInsecureDomain("www.example.org") setting to permit the communication from HTTP to HTTPS.

The security.allowDomain() restrictions have evolved with each new version

Flash Player cross-domain security rules have evolved with the security model of the player. Developers should take this into account when deciding which version of their Player to specify in compiling their SWF. The following table summarizes the differences (see Table 2).

Table 2. Cross-domain security rules implemented by different versions of Flash Player

Latest SWF version involved in cross- scripting 5 or
earlier
6 7 8 or
later
allowDomain() needed? No Yes, if super-domains don't match Yes, if domains don't match exactly Yes, if domains don't match exactly
allowInsecureDomain() needed? No No Yes, if performing HTTP-to -HTTPS access (even if domains match exactly) Yes, if performing HTTP-to -HTTPS access (even if domains match exactly)
Which SWF must call allowDomain() or allowInsecureDomain()? N/A The SWF file being accessed, or any SWF file with the same super-domain as the SWF file being accessed The SWF file being accessed, or any SWF file with exactly the same domain as the SWF file being accessed SWF being accessed
What can be specified in allowDomain() or allowInsecureDomain()? N/A

In Flash Player 9, using this API applies only to the SWF file that calls them, not to other SWF files from the same domain.

It is important to not that the behavior of Flash Player is defined by the version you select in the Publish settings when you create the SWF file from the FLA file and is not based on the version of Flash Player itself. For example, when Flash Player version 9 is playing a SWF file published for version 7, it applies behavior that is consistent with version 7. This practice ensures that backwards compatibility is maintained and that player upgrades do not change the behavior in deployed SWF files.

Setting Security.allowDomain() permits more than just cross-scripting

The Security.allowDomain() method grants access for cross-scripting, accessing the display list, access to the Stage object and event detection. This will also mean that HTML-to-SWF scripting is granted to the remote domain. For instance, if you have registered a callback function via ExternalInterface.addCallback(), and the HTML is hosted on a separate domain than your SWF file, then the Security.allowDomain() will need to contain the domain of the hosting HTML page in order to access the callback function. HTML-to-SWF communication is discussed later in the "JavaScript relaying" section of this article. Allowing cross-scripting between two domains should only occur when the script allowing access explicitly trusts the domain that is being granted access. Cross-scripting will allow access to all of the objects and methods within the SWF granting permission.

If a parent wants to determine whether it can cross-script with a SWF that it has just loaded, it can check the childAllowsParent property of LoaderInfo in ActionScript 3.0. Likewise, a loaded SWF can determine if it can communicate with its parent via the parentAllowsChild property of ActionScript 3.0.

Sharing events across security boundaries

Another important consideration with regards to error handling is that display events do not cross security boundaries. Cross-scripting permissions must be granted by Security.allowDomain() in order to register event listeners across boundaries. If using the Security.allowDomain() is too permissive for your implementation, then the sharedEvents event dispatcher within the LoaderInfo object can be used to send messages across security boundaries:

//Parent.SWF
// The parent SWF registers an event listener that it will
// send to a child
loader:Loader = new Loader();
loader.load(new URLRequest("http://remote.com/remote.swf"));
addChild (loader);
stage.addEventListener(FocusEvent.FOCUS_IN, focusInListener);
//The Parent listener will forward the event to the remote child
function focusInListener (e:FocusEvent):void {
   loader.contentLoaderInfo.sharedEvents.dispatchEvent(e);
}
//Remote.SWF
// The remote SWF registers to receive the event
loaderInfo.sharedEvents.addEventListener(FocusEvent.FOCUS_IN, focusInListener);
//The remote SWF does something with the event
function focusInListener (e:FocusEvent):void {
   // Do something
}