Accessibility

Table of Contents

Creating more secure SWF web applications

Communicating through a shared resource

The next three methods describe considerations for communicating through a shared resource. These methods do not require the target SWF file to be loaded, and they can allow communication to more than one SWF file. Shared resources can include local connections, local shared objects, and JavaScript relaying.

Controlling LocalConnection communication

Related threats: Cross-domain privilege escalation, malicious data injection, insufficient authorization restrictions

To find the documentation for the content discussed in this section, see LocalConnection in the ActionScript 3.0 Language and Components Reference.

You can use a LocalConnections object to allow two or more SWF files to communicate with each other if they are both being hosted simultaneously on the same machine. LocalConnection was originally designed for interprocess communication and is limited to sending messages of less than 40K in length. Since the only requirement is that both SWFs are running simultaneously on the same machine, the two SWF files do not need to be running in the same browser. The allowDomain() method within the LocalConnection object is used to authorize access to the LocalConnection. The identifying name of a connection is the domain name attached to the connection name that you've assigned. The domain name is also sent in the sendingDomain parameter of allowDomain. The LocalConnection.allowDomain method is an assignable method for checking authorization.

The code example below shows how to add the superdomain as a prefix of the connection name:

// Receiving LocalConnection SWF
// For Flash Player 6 hosted on www.example.com uses superdomains
// for authorizing the connection in allowDomain
receiving_lc.allowDomain = function(sendingDomain) {
   return(sendingDomain=="example.com");
}
receiving_lc.connect('myConnection');

// Sending LocalConnection SWF
// sendingLC in http://store.example.com/sending.swf connects by
// prefixing the superdomain to the connection name
sendingLC.send('example.com:myConnection', 'myMethod');

If you are working with files authored for Flash Player 7 or later, the sendingDomain parameter contains the exact domain of the caller. In this situation, the

// Receiving LocalConnection (AS2)
// AS2 code for Flash Player 7 hosted on www.example.com
receiving_lc.allowDomain = function(sendingDomain) {
return(sendingDomain=="store.example.com");
}
receiving_lc.connect('myConnection');

// Receiving LocalConnection (AS3)
// AS3 code for Flash Player 9 hosted on www.example.com
receiving_lc.allowDomain("store.example.com");
receiving_lc.connect('myConnection');

// Sending LocalConnection (AS2 or AS3)
// sendingLC is in http://store.example.com/sending.swf
// Even though the receiving SWF uses full domain, the sending SWF
// only uses the superdomain
sendingLC.send('example.com:myConnection', 'myMethod');

Beware of using wildcards on LocalConnections

As a shortcut during the development phase, Flash supports the "*" wildcard to accept localConnections from multiple domains. Additionally, you can prepend a "_" on the connection name to make the connection globally accessible. These features should only be used for debugging during development. As a general rule, never allow these shortcuts to be present in production code since any SWF from any site can connect to the localConnection:

// receivingLC is in http://www.example.com/receiving.swf
// Doing this can be risky since ANYONE can connect!
receivingLC.allowDomain('*');
receivingLC.connect('_myConnection');
// sendingLC is in http://www.someotherdomain.com
sendingLC.connect('myConnection');

Use a multiple domain whitelist rather than wildcards in allowDomain

During testing, if you wish to avoid the wildcard feature, you can alternately write more complex logic for the allowDomain function that lists all of the allowed callers:

// For Flash Player 7 or later (AS2)
receiving_lc.allowDomain = function(sendingDomain) {
   return(sendingDomain=="www.domain.com" ||
      sendingDomain=="store.domain.com");
}
 
// For Flash Player 9 or later (AS3)
Receiving_lc.allowDomain("www.domain.com", "store.domain.com")

Be cautious when specifying allowDomain using LoaderInfo information

If the domain name of a loaded SWF is not known at compile time, these properties can be used dynamically to obtain the domain name instead of using a wildcard. However, keep in mind that in some cases, any site on the Internet can load the SWF:

// If the parent does not know the child domain
// This can be risky if you loaded using a FlashVar!
Security.allowDomain(loader.contentLoaderInfo.url)

// If the child does not know the parent domain
// Keep in mind that ANYONE can load your SWF!
Security.allowDomain(this.root.loaderInfo.loaderURL)

If you are working with files authored for Flash Player 7 or later, it is not possible to use this method to allow SWF files hosted using a secure protocol (HTTPS) allow access from SWF files hosted in nonsecure protocols. In this situation, the LocalConnection.allowInsecureDomain event handler can be used for these scenarios but it is not recommended.

allowDomain and allowInsecureDomain APIs do not acknowledge ports numbers

Remember that Flash Player matches connection permissions based on domains and protocols. What domain names you supply, and whether you use wildcards, instructs Flash Player on what domains to allow. Your decision whether to use the LocalConnection.allowDomain or the LocalConnection.allowInsecureDomain function tells Flash Player whether to allow cross-protocol connections. However, Flash Player does not differentiate between a SWF loaded over HTTP from www.example.org:80 and one loaded over HTTP from www.example.org:8080. Flash acknowledges that the SWF came from www.example.org and that it was loaded over HTTP when making the security decision, but Flash Player ignores whether the SWF was loaded from port 80 or port 8080. Therefore, developers should be sure that they trust all web servers running on the remote domain before granting permissions.

Security considerations when using local shared objects

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

To see details about working with local shared objects, see SharedObjects in the ActionScript 3.0 Language and Components Reference.

If you'd like more information about working with third-party local shared objects, read What are third-party local shared objects?

Local shared objects (LSOs) are a mechanism provided for persistent storage of small amounts of data. Access to this data is segmented by looking at three components: the domain hosting the SWF, the local path of the SWF and whether the SWF was loaded via HTTPS. The domain is always checked to ensure that one domain cannot access another domain's SWF data. The domain is also checked in situations where a domain is hosting third-party SWF files. End-users have the ability to change the default setting of Flash Player to deny third-party SWF files the ability to create local shared objects. If the user changes this setting, SWF files hosted on the same domain as the web page will be able to create local shared objects but any SWF files imported from another

Set the localPath variable carefully

Local shared object data is also segmented by the URL path. By default, the shared object is restricted to the full path in the URL which includes the name of the SWF file. This means that only the SWF file creating the shared object can access the shared object. However, permission to the shared object can be expanded to permit additional access based on path. For example, if the SWF file is located at http://www.mydomain.com/path1/path2/path3/my.swf, then the SWF can configure the shared object to allow access from other SWF files within /path1, /path1/path2, or /path1/path2/path3 by setting the initial localPath value to one of those three choices. Some designers will specify "/" when creating their local shared objects so that all the SWF files in the domain can share the same data. This setting is not recommended because you can create issues for developers in shared environments in cases where independent groups are all hosted under the same domain. If the SWF file will be hosted by a third-party that hosts content from other developers, it is a best practice

The code example below shows how to specify the localPath to the local shared objects:

// This will get the local shared object "userInfo" that is stored
// based on the full path of the SWF and is available to only SWF files
// served over HTTP
var mySO = SharedObject.getLocal("userInfo", "/path1/path2", false); 

The secure flag can be used to protect shared objects

If you are working with SWF files that run in Flash Player 8 and later, an additional secure flag was added to shared objects so that SWF files served over HTTPS could create shared objects that are accessible only to other SWF files served over HTTPS from the same domain. This means that a SWF served over HTTP cannot access the secure shared object set by the SWF served over HTTPS—even if it is the same SWF file. The flag defaults to "false" so that any SWF from the same domain and path can access the shared object and to ensure that SWF files created prior to Flash Player 8 will not be affected.

Like other Flash Player security controls, the security comparison does not acknowledge the port used to load the SWF file. Therefore, if the secure flag is set to true, then a SWF loaded over HTTPS from port 443 and a SWF loaded over HTTPS from port 8443 would both be allowed access to the LSO because they were both loaded over HTTPS from the same domain.

The following code example describes how to access local shared objects across SWF files served over HTTPS from the same domain:

// This will get the local shared object "userInfo" that is stored
// based on the full path of the SWF and is available to only SWF files
// served over HTTPS
var mySO = SharedObject.getLocal("userInfo", null, true); 

The data that is stored in a local shared object is kept in a serialized, binary format. However, the data is not encrypted. Local shared objects are not secure, as developers have created several free tools to read and write to local shared object files. Also, like cookies, shared objects are limited by are user-controlled settings. An end-user can choose to alter the storage size of local shared objects or choose to deny storage completely. For these reasons, local shared objects should not be used to store anything that cannot be destroyed or altered in your application:

static function getRemote(name:String, remotePath:String, persistence:Object, secure:Boolean) : SharedObject;

In addition to storing data locally in a local shared object, data can be stored remotely on a Flash Media Server over RTMP using the getRemote() method of a shared object. Consider carefully as you decide upon which data is sent over RTMP, since it is not encrypted. Attackers monitoring network traffic can capture data sent in an RTMP stream. If sensitive data must be sent, you should use an RTMPS or an RTMP over HTTPS connection instead.

Do not override the default for Security.ExactSettings

Related threats: Insufficient authorization restrictions

If you would like to see more information about the options available using exactSettings in ActionScript 3.0, see exactSettings in the ActionScript 3.0 Language and Components Reference.

When Security.exactSettings is set to true, Flash Player uses exact domains for player settings in SharedObjects and camera/microphone permissions. It doesn't affect settings such as crossdomain.xml comparisons. When this property set to false, Flash Player uses domain settings used in Flash Player 6 which would drop the value before the first period in the domain.

For example, when exactSettings is set to false, then the domain www.example.com and the domain store.example.com are both considered to be in the domain example.com and are therefore treated the same.

When exactSettings is set to true, the store.example.com and www.example.com are considered to be different domains. The default value for exactSettings is true. One of the few instances where changing exactSettings to false is necessary is when accessing shared objects created by Flash Player 6. Changing exactSettings from its default value must be performed before any events occur that require Flash Player to choose player settings—such as using a camera or microphone, or retrieving a persistent shared object. 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. All programs should leave exactSettings set to true whenever possible.

JavaScript relaying

Related threats: Malicious data injection, insufficient authorization restrictions

For more information on interacting with JavaScript within the HTML page, refer to ExternalInterface and fscommand() in the ActionScript 3.0 Language and Components Reference.

Some developers will set the allowScriptAccess tag to always in order to allow cross-domain communication via JavaScript. They may also permit cross-domain HTML-to-SWF communication for addCallback functions through flash.system.Security.allowDomain() permissions. With these settings, the SWF files can use fscommand, ExternalInterface.call, ExternalInterface.addCallback or a URL navigation containing the javascript: protocol to communicate with the web page. Script access will be granted to the

fscommand(), ExternalInterface.call(), and cross-site scripting

JavaScript relaying across-domains can be effective but setting allowScriptAccess to always can also be very risky because the communication is not restricted to any specific domain. Many complex web pages include advertisements which link together code from several remote domains. Since the SWF is communicating with the web browser, there is the possibility for cross-site scripting if data validation is not performed. Developers have to keep in mind that allowScriptAccess not only allows fscommand() and ExternalInterface.call() methods but it also allows getURL() and NavigateToURL() calls which could contain javascript: URLs to script with the browser.

The ExternalInterface.call() method can act similarly to a JavaScript eval() call and any injected data could result in arbitrary JavaScript code execution within the browser. Using fscommand() instead of ExternalInterface.call() can limit the attack surface available to an attacker when untrusted external data is passed to the web page. However, using fscommand will only limit how the SWF interacts with the browser and it can not fully eliminate the possibility of a cross-site scripting attack. Therefore script access should be limited to a single domain whenever possible.

In addition, data received from the ExternalInterface.addCallback function should have data validation performed on it before being processed by the SWF. If a cross-site scripting vulnerability exists within the web page itself, an attacker can leverage that to send malicious data to the SWF. There is also the possibility the SWF is being loaded by an untrusted web page. Therefore, developers should ensure that they avoid setting wildcards within Security.allowDomain() in order to permit the surrounding HTML to access the callback function. In addition, whenever data is received from an external resource, data validation should be performed.

Using LocalConnections as an alternative cross-domain JavaScript relaying

Since the allowScriptAccess tag is an all or nothing approach to granting access to the web page, you may want an alternative that is more restrictive. One way to avoid setting allowScriptAccess to always but still allow some cross-domain communication with the page is to create a trusted SWF within your domain that has script access and has a LocalConnection method exposed. Access to the LocalConnection can then be limited to specific domains through the LocalConnect.allowDomain settings. Untrusted SWF files from other domains will be able to send data to the exposed LocalConnection methods. Once the data is received, the trusted SWF can verify the data and make the necessary script calls into the web page.