Requirements

Prerequisite knowledge

You should have an understanding of ActionScript 2.0, ActionScript 3.0, and Flash Player. Knowledge of Flash CS4 Professional or Flex is encouraged but not required.

User level

Intermediate

 

Required products

Flash Player

 
Additional Requirements

 
Flash CS4 Professional (optional)
 
Flex Builder 3 (optional)
Note: This article was originally authored for Adobe Flash Player 9,0,115,0 and has been updated for Flash Player 10. Changes to this article were made to reflect updates to cross-domain HTTP and socket policies, user-initiated action requirements, and other protections added in Flash Player 10. The article was also updated to reflect recent projects, clarifications on Flash Player port usage, and additional best practices.
 
Adobe frequently updates the Flash Player software security model to improve the security of the Flash Player environment. However, that only addresses half of the overall solution to help securely deploy applications that run in Flash Player. As the web developer, you must also correctly leverage the tools provided by the Adobe ActionScript language and the Flash Player platform to help ensure that your SWF files are more secure. Poor programming conventions can expose SWF files and the sites that host them to web attacks. Adobe provides many resources for developers—such as the Flash Player security section of the Programming ActionScript 3.0 for Flash documentation—to assist with developing more secure code.
 
This article outlines many of the security considerations associated with common tasks and provides samples of techniques that can be used to help secure code against those threats. Links to the full documentation are provided throughout the article for further reference.  These techniques are designed primarily for the Adobe Flash development environment but they can also be applied by Adobe Flex developers.
 
This highly technical article presumes that you have some knowledge of the ActionScript language and Flash development. Due to its length, the article is broken up into different sections based on what you are trying to accomplish as a developer or administrator:
 
  • If you are an administrator who deploys Flash applications, you will be interested in the sections on HTML controls, domain segmentation, cross-domain policy files, and socket policy files.
  • If you are a developer who creates simple, self-contained SWFs such as advertisements, you will most likely be interested in the sections on data validation on URLs, JavaScript communication, and local shared objects.
Most of this article is targeted for those who create complex websites using the Adobe Flash Platform. Throughout the article, there are links to additional resources for greater detail on all the issues discussed.
 

 
Potential threats to SWF files

This section provides a brief overview of the different high-level threats that you should consider when developing SWF applications. Although there are more granular threats that could be defined within a specific context for any SWF file, this overview covers the high-level threats common to most SWF deployments. Throughout the rest of the document, "Related Threats" entries will map these threats to specific Flash Player APIs and concepts. Each section will then describe the mitigation strategies that apply to the identified threats.
 
 
Cross-domain privilege escalation
Cross-domain loading may allow a remote SWF to have unintended access to the loader's domain and data. If the loading SWF imports the remote SWF file into its security domain, then the loaded SWF could gain access to the parent SWF's data and relay that data back to an attacker. In addition, depending on settings within the web page, the loaded SWF could inject script into the loaded SWF file's web page. These attacks could occur whenever the end-user can gain control over movies that are loaded by a parent SWF file. Cross-domain privilege escalation is a high-level threat that can expose a SWF to more specific threats such as spoofing, script injection into the browser, malicious data injection, DNS rebinding and insufficient authorization restrictions. This threat exists whenever content from multiple remote sources is loaded and processed under a single security domain.
 
 
Spoofing
A remotely loaded SWF may try to render its controls over the top of the loading SWF in an attempt to perform a spoofing attack. By overlaying the parent SWF, the malicious SWF can hijack control from the loading SWF file. For instance, if developers do not set masks on Loaders to limit the remote SWF file to a particular area of the Stage then an attacker could perform a spoofing attack.
 
 
Malicious data injection
Injecting malicious data into applications is how most vulnerabilities are found by attackers. A Flash application may receive malicious data injection from several types of interfaces. For example, it is common for FlashVars to be set via the Object tag within the HTML. However, developers sometimes forget that these variables can be set via the URL where it is trivial for an attacker to alter the values. For example, if the FlashVar value is a URL that points to remote content such as another SWF, then the attacker could alter the URL to point to a malicious SWF instead. In ActionScript 2.0, any uninitialized value can automatically be set via the URL as a FlashVar. In ActionScript 3.0, you must explicitly request the value of each FlashVar variable and manually assign that value to an internal variable.
 
Other examples where malicious data inject can include any time a SWF loads remote data—such as when a SWF file obtains data from a LocalConnection, the SWF file remotely loads variables from a server, or the SWF file imports data from another SWF file. A SWF file will be exposed to this threat if you do not perform data validation on remotely obtained data.
 
 
Script injection into the browser
In some instances, website owners may host third-party SWF files on their site. However, the website owners may not want to grant the third-party SWF files read and write access to their HTML or JavaScript code. Incorrectly setting permissions could allow an attacker to rewrite the entire page or redirect the users from the trusted site to a phishing site. This threat exists for web administrators that host third-party SWFs as well as for SWF files that accept URLs via FlashVars.
 
The most common vulnerability to consider is an attacker injecting data in order to conduct a cross-site scripting (XSS) attack. Assume that the target SWF takes a URL value from a FlashVar and sends that information to a navigateToURL or a getURL command. An attacker who notices this behavior may try to replace the original URL value of the FlashVar with a "javascript:" URL. JavaScript URLs sent to the browser through getURL or navigateToURL methods will execute within the context of the domain hosting the SWF. The javascript: URL can contain any set of JavaScript commands including commands to steal the cookies from the domain and forward them to a third-party site. A cross-site scripting attack could also occur if a malicious remote SWF is imported into the trusted SWF and then the remote SWF calls a javascript: URL.
 
These attacks can be considered to be a special subset of the malicious data injection attacks. They are separated out from malicious data injection because, as we will discuss later, Flash Player has controls that can help prevent cross-site scripting attacks but would not prevent the more general data injection attacks.
 
 
Insufficient authorization restrictions
Excessive cross-domain permissions may allow relay attacks, spoofing, data theft or other attacks. For example, a malicious SWF file may try to exploit overly permissive cross-domain policy file permissions to steal protected data from a remote website. Another example might be an untrusted SWF that is able to send malicious data to another domain via a LocalConnection. Weak domain restrictions can occur when wildcards are misused in allowDomain methods or cross-domain files.
 
Developers often consider a cross-domain threat to be domain www.a.com gaining unauthorized access to www.b.com. However, developers must also consider whether their SWF files will be hosted within a shared environment. This can include situations where a developer's content is hosted under http://www.host.com/~user1 and the content under http://www.host.com/~user2 is not explicitly trusted by the developer. This can also occur in advertising situations where ads from multiple sources are hosted on the same domain. There are situations where Flash Player takes directory and file paths into account in determining authorization such as with LocalConnections. There are other situations where only the hosting domain is considered such as allowDomain() settings. Developers need to take shared hosting situations into account when designing mitigations to this threat.
 
 
Unauthorized access to data in transit
An attacker may try to read or alter data sent over unencrypted channels such as RTMP and HTTP. If the SWF file is performing critical functions (such as collecting credit card data within a shopping cart), then the attacker could potentially view that data. An attacker may also try to manipulate traffic and attempt to replace the trusted SWF files with malicious SWF files before they reach the end-user. Vulnerabilities for this threat include when secure communication channels such as HTTPS or RTMPS are not used to protect sensitive data.
 
Insecure communications can also occur when SWF files loaded over HTTP can access the data of SWF files loaded over HTTPS. By default, an HTTP-loaded SWF file may not access data from SWF files loaded over HTTPS. However, if data is shared between an HTTP SWF and an HTTPS SWF then the data may be transmitted over an insecure channel. This can occur if an allowInsecureDomain method is misused or when the secure flag is set to false in a crossdomain.xml file.
 
 
Unauthorized local data access
An attacker may attempt to steal sensitive local data from SWF files and local shared objects. SWF files can be decompiled and local shared objects can be read by third-party applications. An attacker may also try to obtain the information dynamically through cross-scripting. This threat includes vulnerabilities such as when developers store sensitive data within SWF applications and shared objects.
 
 
Cross-site request forgery
Cross-site request forgery (XSRF) is where an attacker exploits a user who has visited their website by initiating an unauthorized request to another site to which the user is authenticated. If the target website utilizes atomic (single submit) actions for updates to user information, then the attacker can initiate a change to the user's account on that site by forcing the browser to make a request to the site. The attacker does not need the user's cookies to perform the attack since the browser will automatically append them to the request. The attacker is usually unable to directly see the results of their update but the change will be made nonetheless. Due to the current design of the web, protections against these attacks are currently being implemented by the websites themselves and not by the browser or its clients. Since Flash Player utilizes the browser to make web requests, Flash Player can be used as a tool in performing cross-site request forgery attacks.
 
 
DNS rebinding
Web browsers and Flash Player use domain names for establishing authorization to data as part of the same-origin policy. An attacker can try to bypass the same-origin policy by tricking the web browser to continually update the IP address it has recorded for a particular domain name. For this attack to work, the attacker must have a DNS server under their control and a malicious website. Through varying techniques, the attacker can update the IP address for their domain name within their DNS server and then force the web browser to retrieve the updated information. Therefore, the attacker can make their domain name first point to the IP of their public website, then point to an IP of a trusted server on the victim's internal network and then point back to their public website.
 
For all of these requests, only the IP address is changing and the domain name used to establish the requests remains the same. Since the domain name remains the same for all requests, the web browser considers the connection to the trusted internal server and the connection to the attacker's public web server to be equivalent with regards to security. This allows the attacker to steal information from the internal web server and send that data back to the public website. For many types of requests, Flash Player relies on the hosting web browser to establish HTTP connections. Therefore any DNS rebinding attack that is applied to the web browser will also affect Flash Player. This attack may also be applied to Flash socket connections in versions of Flash Player prior to version 9,0,124,0.
 
 
Clickjacking
Clickjacking is an attack that applies the invisible property of style sheets to HTML div tags or iframes in order to transparently overlay malicious content on top of trusted content. By making an iframe or div tag invisible, an attacker can hide malicious content underneath the mouse. Since these tags can also float, they are able to follow the mouse around the web page. When the user attempts to click something on the web page, they will actually click the invisible div tag that was following their mouse around the page. This allows an attacker to trick the user into clicking anything that they want.
 
Within Flash Player 10,0,12,0 and Flash Player 9,0,152,0, Adobe added protections against clickjacking to sensitive Flash Player controls such as the camera and microphone permission dialog box. However, the more general case of using clickjacking to commit click fraud against SWF- or image-based advertisements still remains in the web browser.
 

 
Selecting more secure compiler settings

In this section I discuss the optimal settings to use in the Publish Options in Flash CS3 Professional to help security in your Flash applications.
 
To see more information regarding this topic, see Specify publish settings for SWF files in the Using Flash CS4 Professional documentation.
 
The first consideration a developer makes is what Flash Player version the SWF application should be compatible with. All modern versions of Flash Player include an auto-update feature to notify users when a new version of the player is available and this has been highly successful in getting the majority of Flash Player users migrated to new versions quickly. The Flash Player home page tracks market penetration of the players and shows how quickly new versions are adopted (see Adobe Flash Player version penetration). Flash Player 9 compatibility achieved 90% cross-platform market penetration within approximately one year while Flash Player 8 compatibility has over 98% cross-platform penetration in major markets. For some applications, reaching 98% of customers is sufficient. However, for global organizations, the inability to reach 1.5% of the hundreds of millions of systems on the Internet still results in not reaching a few million systems. Some of the systems with older versions of Flash Player include older operating systems or systems that are part of a locked environment where they do not receive updates unless absolutely necessary due to system stability.
 
Newer versions of Flash Player frequently contain important security updates and features which can help to ensure that SWF files are not misused on the hosted website. Due to backwards compatibility requirements, in some instances Flash Player determines whether to enforce the additional security changes based on the version of Flash Player that the SWF was compiled for and not the version of Flash Player that is executing the SWF. For example, if the end-user has the latest version of Flash Player installed (version 9) but the end-user is playing a SWF file that a developer compiled for Flash Player version 7, then, in some instances, the end-user's Flash Player will mimic the behavior of Flash Player 7—which has a less mature security model for both the site developer and the end-user. One example would be that the default for "allowScriptAccess" is "always" in SWF files compiled for compatibility for Flash Player 7 and "sameDomain" for SWF files compiled for Flash Player 8. Consequently, you should compile for compatibility with Flash Player 8 or later to ensure that the SWF uses the more secure setting.
 
Additionally, you access better security tools when leveraging ActionScript 3.0. Developers using ActionScript 3.0 can take advantage of regular expressions which can make the process of performing data validation easier. Input controls within the language are more centralized. In addition, the AVM2 virtual machine used to process ActionScript 3.0 is faster, more robust and more stable then the AVM1 environment that supports the legacy ActionScript 2.0 and ActionScript 1.0 code. Developers who want to migrate from ActionScript 2.0 to ActionScript 3.0 should read Migrating from ActionScript 2.0 to ActionScript 3.0: Key concepts and changes, as well as check out the migration resources in the ActionScript Technology Center.
 
If you want to ensure your end-users are using a current version of Flash Player, then you can use the Flash Player Detection Kit provided by Adobe. It contains both client-side JavaScript and ActionScript code for detecting the Flash Player version and determining if the version is appropriate for your content.
 

 
Using the protect from import and permit debugging options

 
Related threats: Unauthorized local data access
The Protect From Import and Permit Debugging flags use an MD5 hash to password-protect SWF files from import into a Flash authoring tool. This protection is a basic protection for authoring tools that choose to honor it. A determined attacker could still decompile the SWF file to get the source code or strip the debugging flag from the binary. The MD5 hash used by these flags is subject to brute force dictionary-based attacks. Therefore, SWF files should not be considered to be a black box application even with the Protect From Import flag set. Any sensitive data or secrets stored within a SWF can easily be found. Developers should not store static passwords, encryption keys or other sensitive data within the source code of a SWF file.
 

 
Compiling clean code

 
Related threats: Unauthorized local data access
When creating applications, it is a best practice to remove all debug code from the final production releases. This is also a best practice for developing SWF applications. The Omit Trace Actions flag in Flash development environments tells the compiler to remove any trace commands when creating the compiled SWF file. This will make the published SWF smaller and it will remove any excess information or actions from the SWF.
 

 
Setting the minimum stage size

 
Related threats: Spoofing, clickjacking
The stage size should be set to a minimum of 215 pixels wide and at least 138 pixels high so that Flash Player messages from shared objects, microphone, camera and other components can be displayed fully to the user. To protect against clickjacking attacks, Flash Player requires the area of the stage displaying the dialog box to be visible with the default window mode set.
 

 
Setting security controls within the HTML code

When a SWF is embedded within HTML, there are several flags that can be set that tell Flash Player the permissions the SWF file has to access content either from the browser or on the network. These flags are useful for sites that may link to untrusted SWF files from third-party developers.
 
In addition to the strategies described below, refer to the "How to restrict SWF content from HTML" blog post for additional information.
 

 
Using allowScriptAccess

 
Related threats: Script injection into the browser
To learn more about controlling access to HTML scripts, see the section entitled Controlling outbound URL access in the Programming ActionScript 3.0 for Flash documentation.
 
The allowScriptAccess setting has been available since Flash Player 6,0,40,0. It determines whether a parent SWF file and any SWF files loaded by the parent SWF file can make outbound scripting calls to the browser through commands such as fscommand() and ExternalInterface() or sending "javascript://{code}" statements to getURL (in ActionScript 2.0) and navigateToURL (in ActionScript 3.0). Inbound calls from HTML to ActionScript code are controlled by the Security.allowDomain() ActionScript call, which is discussed later in this document.
 
When you grant access to the SWF file, remember that you are essentially granting both read and write access to the entire HTML page.
 
The three possible settings for allowScriptAccess are:
 
  • always: The SWF file is completely trusted to communicate with the browser regardless of the domain used to load it. All SWF files loaded by this SWF are also granted permission to communicate with the browser. This is the default for SWF files compiled for compatibility with Flash Player 7 and earlier when using versions of Flash Player prior to 9,0,124,0.
  • sameDomain: If the SWF and the hosting HTML page are located within the same domain, then they may communicate with each other. If you are using a version of Flash Player prior to 9,0,124,0, this is the default for SWF files compiled for compatibility with Flash Player 8 and later. If you are using Flash Player 9,0,124,0 or later, then it is the default for all content regardless of the Flash Player version for which the content was compiled.
  • never: The SWF and the browser are never allowed to communicate with each other through JavaScript. This setting has been deprecated. Please see the following TechNote for more information: Deprecation of the "never" setting for allowScriptAccess.
It is also important to note that the allowNetworking tag can affect script access within the browser and will supersede the settings used for the allowScriptAccess tag.
 
Review the highlighted sections in the following code example:
 
<object id='MyMovie.swf' classid='clsid:D27CDB6E-AE6D-11cf-96B8-444553540000' codebase='http://download.adobe.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0' height='100%' width='100%'> <param name='allowScriptAccess' value='never'/> <param name='src' value=''MyMovie.swf'/> <embed name='MyMovie.swf' pluginspage='/go/getflashplayer' src='MyMovie.swf' height='100%' width='100%' allowScriptAccess='never'/> </object>

 
Understanding allowNetworking

 
Related threats: Script injection into the browser, cross-domain privilege escalation
To augment the information provided below, read the Restricting networking APIs section of the Programming ActionScript 3.0 for Flash documentation.
 
The allowNetworking feature was added in Flash Player 9 to prevent a SWF from making external networking calls through the browser or through ActionScript networking calls. The allowNetworking settings will supersede the allowScriptAccess settings since methods controlled by the allowScriptAccess tag are a subset of the overall class of ActionScript networking methods:
 
The three possible settings for allowNetworking are:
 
  • all: The SWF is completely trusted to make any network connections. Communication with the browser will be controlled by allowScriptAccess. This is the default setting.
  • internal: The SWF is prevented from making navigateToURL(), fscommand() and ExternalInterface.call() ActionScript 3.0 commands. For ActionScript 2.0 developers, getURL(), MovieClip.getURL(), fscommand(), and ExternalInterface.call() will be restricted. This overrides any allowScriptAccess setting and blocks the SWF from communicating with the browser. All networking calls must be made internally inside the SWF.
  • none: This is the most restrictive tag that can be set within the HTML. This will block the SWF from performing any external communication.
For ActionScript 3.0, the blocked networking methods include sendToURL()FileReference.download(), FileReference.upload(), Loader.load, LocalConnection.connect(), NetConnection.connect(), NetStream.play(), Security.loadPolicyFile(), SharedObject.getLocal(), SharedObject.getRemote(), Socket.connect, Sound.load(), URLLoader.load(), URLStream.load(), XMLSocket.connect(), System.security.loadPolicyFile(), as well as those methods blocked by the internal setting.
 
For ActionScript 2.0, the blocked networking methods include XML.load(), XML.send(), XML.sendAndLoad(), LoadVars.load(), LoadVars.send(), LoadVars.sendAndLoad(), loadVariables(), loadVariablesNum(), MovieClip.loadVariables(), NetConnection.connect(), NetStream.play(), loadMovie(), loadMovieNum(), MovieClip.loadMovie(), MovieClipLoader.loadClip(), Sound.loadSound(), LocalConnection.connect(), LocalConnection.send(), SharedObject.getLocal(), SharedObject.getRemote(), FileReference.upload(), FileReference.download(), System.security.loadPolicyFile(), XMLSocket.connect(), as well as those methods blocked by internal setting.
 
It is also not possible to reference external media in an <img> tag in the htmlText property of a TextField object (because a SecurityError exception is thrown). Symbols from an imported shared library added in the Flash authoring tool (not ActionScript) are blocked at run time.
 
Review the highlighted sections in the code example below:
 
<object id='MyMovie.swf' classid='clsid:D27CDB6E-AE6D-11cf-96B8-444553540000' codebase='http://download.adobe.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0' height='100%' width='100%'> <param name='allowNetworking' value='none'/> <param name='src' value=''MyMovie.swf'/> <embed name='MyMovie.swf' pluginspage='/go/getflashplayer' src='MyMovie.swf' height='100%' width='100%' allowNetworking='none'/> </object>
 
allowNetworking supersedes the allowScriptAcess methods
The results of combining the allowNetworking and allowScriptAccess flags are shown in Table 1.
 
Table 1. Network and access settings for different levels of security
 
allow
ScriptAccess
allowNetworking
 
All
 
Internal
 
None
 
Always
 
The SWF has full access to communicate with the browser and the network. This is the least secure setting.
 
The allowNetworking setting will override the allowScriptAccess setting and disallow access to the browser. The SWF is still able to leverage internal APIs such as sockets and loaders to communicate with the network.
 
The allowNetworking setting will override the allowScriptAccess setting and prevent the SWF from communicating to the browser and the network.
 
SameDomain
 
The SWF can talk to the HTML container if they are both within the same domain. All internal networking APIs are allowed.
 
The allowNetworking setting will override the allowScriptAccess setting and disallow access to the browser. The SWF is still able to leverage internal APIs such as sockets and loaders to communicate with the network.
 
The allowNetworking setting will override the allowScriptAccess setting and prevent the SWF from communicating to the browser and the network.
 
Never (deprecated)
 
The SWF can not make calls to the browser but it can make network calls using internal APIs such as sockets and loaders.
 
This SWF can not communicate with the browser. The SWF is still able to leverage internal APIs such as sockets and loaders to communicate with the network.
 
The allowNetworking setting prevent the SWF from communicating to the browser and the network. This is the most secure setting.
 

 
Understanding that SWFs are code

When you make the decision to host SWF content on a particular domain, it is important to remember that SWF files are code. By default, SWF files will have the same permissions on the hosting domain as JavaScript. Therefore, developers should not host untrusted code on the same domain as trusted code.
 
One reason is that when a SWF is referenced without any surrounding HTML, such as when a user clicks a link that points directly to the SWF, the defaults for allowScriptAccess and allowNetworking are applied, granting the SWF access to the DOM. This attack may be used by an attacker to conduct cross-site scripting or other malicious attacks. Adobe strongly recommends against mixing trusted and untrusted content on the same domain. The best place to host untrusted content is on a separate IP address that does not have a domain name associated with it. See the section "Segmenting SWFs from trusted content" elsewhere in this article for more information.
 
Some sites may try to mix trusted and untrusted content on the same domain by placing the untrusted content in a non-web accessible directory and carefully controlling access through a CGI. This implementation is difficult to implement correctly, and developers should take into account all of the permissions that a SWF is granted by being hosted on the same domain as trusted content. For instance, cross-scripting and LocalConnections are allowed by default to SWFs hosted from the same domain.
 

 
Controlling full-screen mode

 
Related threats: Spoofing
To find out more about working in full-screen mode, read Exploring full-screen mode in Flash Player 9.
 
You can control the display of full-screen mode using the features included in Flash Player. A website hosting third-party SWF files may not wish to allow the videos to go into full screen mode and overlay the site's content. Essentially, full-screen display could result in end-users being tricked into believing that they are interacting with the hosting website—when in reality they are interacting with the third-party SWF file. By default, the allowFullScreen option is set to false.
 
Adobe has included other controls to limit this scenario: The user must initiate full-screen mode with a mouse click or a keypress event. Upon invoking full-screen display, the end-user will receive an overlay dialog box warning them they are viewing the SWF in full-screen mode with instructions on how to exit. Users cannot enter data into text input fields while the SWF is displayed in full-screen mode. Users and administrators also have the option to prevent full-screen mode within their mms.cfg file.
 
Review the highlighted sections in the code example below:
 
<object id='MyMovie.swf' classid='clsid:D27CDB6E-AE6D-11cf-96B8-444553540000' codebase='http://download.adobe.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0' height='100%' width='100%'> <param name='allowFullScreen' value='false'/> <param name='src' value=''MyMovie.swf'/> <embed name='MyMovie.swf' pluginspage='/go/getflashplayer' src='MyMovie.swf' height='100%' width='100%' AllowFullScreen='false'/> </object>

 
User-initiated action requirements

 
Related threats: Spoofing
To find out more about user-initiated action requirements, read User-initiated action requirements in Flash Player 10.
 
Starting with Flash Player 10, Adobe has added user-initiated action (UIA) requirements around several critical APIs that provide prompts to the user. When an ActionScript API function has a UIA requirement, that function can be called only in response to a user action such as a mouse click or key press. These additions were made in order to prevent potentially harmful actions from being taken by malicious SWF files without the user's consent. These actions include writing to the user's Clipboard, going into full-screen mode, creating pop-up windows, launching a FileReference dialog box, and certain POST operations. You can find a fuller description of these in the article, User-initiated action requirements in Flash Player 10.
 

 
Managing security boundaries

One of the most common tasks you may want to do is fetch images, sounds, or other data from a remote website. If the content is from a different domain than the requesting SWF file, then Flash Player may need to check with the remote domain to confirm whether you have permission to access that content. In addition, you may want to segment your content intentionally and enforce boundaries. The following sections describe how to manage security boundaries to be either more inclusive or exclusive.
 

 
Loading content as data from different domains

 
Related threats: Cross-domain privilege escalation
By default, Flash Player will follow the same-origin policy used by browsers which says that content within a single domain can access all the other content and data hosted on the same domain name. In addition, a site can present content from other domains but it can not directly access the data belonging to those other domains. For example, the same-origin policy will allow a piece of content on www.a.com to access all of the other data associated with www.a.com. The site www.a.com can also include an iframe showing the web page for www.b.com. However, the same-origin policy prohibits www.a.com from accessing www.b.com's cookies or interacting with the JavaScript on www.b.com's page.
 
Flash Player considers the full domain name used to establish the connection to be its security domain. For Flash Player, a SWF file's domain is defined by where the SWF file is hosted. If a web page at the domain www.a.com includes an object tag to load a SWF from the domain www.b.com, then the SWF considers its security domain to be defined by www.b.com. Other SWF files hosted on the www.a.com site will not have full access to the SWF loaded from the www.b.com site because they are loaded from different security domains. Flash Player matches on the complete domain name and therefore the domain www.a.com is considered to be a different security domain from the domain home.a.com. Flash Player also separates content loaded from www.a.com over HTTPS and content loaded from www.a.com over HTTP into separate security domains. Lastly, Flash Player acknowledges the port used to load SWF content. Therefore, Flash will consider http://www.a.com:80 to be a different site than http://www.a.com:8080.
 
Unlike the browser, Flash Player contains several methods for expanding the same-origin protections to include more than one domain name. Therefore the owner of the site www.a.com can tell Flash Player that the site's content can be shared as raw data with the domain home.a.com. This allows website owners with multiple domain names to have interaction between their sites. Many of these methods support the use of wildcards for when developers want to share their data with the world. From a security perspective, wildcards need to be used with discretion since you are allowing everyone access to your data.
 
 
Segmenting SWFs from trusted content
In addition to incorporating many domain names into one security domain, it is also possible to split content into different security domains. This may be necessary if you host SWF files with different trust levels. One way that you can accomplish this is to take advantage of the fact that Flash Player does not associate domain names with IP addresses.
 
If the site www.example.com is hosted at the IP address 1.2.3.4, then Flash Player will consider a SWF loaded by the URL http://www.example.com/my.swf to be in a different security domain then the SWF loaded by the URL http://1.2.3.4/my.swf. This approach can be useful if a site allows untrusted users to upload SWF files. For instance, websites typically create cookies that they assign to their domain names but they rarely create cookies that are assigned to an IP address. In this example, the cookies created for www.example.com won't be sent along with a request to http://1.2.3.4/my.swf and therefore you do not need to worry about the malicious my.swf gaining access to the cookies. In order for this to work, it is important to verify that there are no example.com domain names that resolve via DNS to the IP address 1.2.3.4 in order to ensure complete separation between the content. If an attacker discovers that the domain foo.example.com resolves to 1.2.3.4, then the attacker may try to reload the malicious SWF using http://foo.example.com/my.swf in order to get access to domain cookies or other permissions within your domain. Another issue with hosting potentially untrusted SWF files on your domain is the possibility of phishing attacks.
 
If you use named-based virtual hosting, then you may not have the option of obtaining a second IP address. In this case, you could also register a second domain name for your content. Many large providers use this technique because IP addresses don't scale well in complex environments. Trusted content would be hosted off of http://www.example.com and untrusted content is hosted off of http://www.not-example.com.
 
Some people will try using a different sub-domain for untrusted content, but this approach still has risks. If you set cookies on your website that are accessible to all sub-domains of your site, then SWFs on a sub-domain may be able to access and alter them. Therefore, in this model, sensitive cookies would need to be created using the full domain name for which they apply so that sub-domain hosting the untrusted SWF content cannot access them. This may also have implications if local shared objects, camera, or microphone permission are granted to the super domain.
 

 
Implementing cross-domain files

 
Related threats: Cross-domain privilege escalation, insufficient authorization restrictions
If you'd like to research how to use crossdomain.xml files, read the Permission controls section of the Programming ActionScript 3.0 for Flash documentation, Cross-domain policy file usage recommendations for Flash Player, and the Cross-domain policy file specification.
 
Cross-domain files are one method for expanding the same-origin policy to allow multiple domain names to be considered part of the same origin. A cross-domain policy file is a way for the server hosting the file to acknowledge that its content can be considered to be part of the same origin as domains listed within the cross-domain file. Cross-domain files served from a web server on port 80 or 443 are considered to be HTTP policy files and can control policies for web requests. Cross-domain files hosted from other ports are considered to be socket policy files. Socket policy files will be discussed later.
 
The crossdomain.xml file can be used to specify several aspects of access to the HTTP server:
 
  • What domains are trusted to be within the same origin of the server
  • Whether communication between HTTP and HTTPS content is allowed for the listed domain names
  • Whether SWF files from other domains can send the server custom headers
  • For Flash Player versions prior to 9,0,124,0, it implicitly grants socket access to ports greater than 1024 for SWF files hosted on the same domain as the server
These cross-domain controls are available to the distributor of content and can apply to either the entire website or just one portion. Creators of SWF files also have the ability to define cross-domain controls through the use of the Security.allowDomain() method which I discuss later. The Security.allowDomain() method is a more granular way of granting cross-domain permissions on a per-file basis.
 
It is also important to note that Flash Player, like most browsers, does not prevent cross-domain sending of data. Flash Player only attempts to prevent cross-domain loading of data. If the website at home.a.com wants to perform an HTTP POST of data to www.a.com using a method that does not return a response to Flash Player, then it can do so without the need for a cross-domain file. If the SWF at home.a.com needs to access the response data from the request, then a cross-domain policy file is necessary.
 
Here are some situations that require using the crossdomain.xml file:
 
  • When performing image extraction, such as using Bitmap.draw() or Loader.content, is required to a movie or image from another domain
  • When performing sound data extraction on sound loaded from another domain such as ID3Info and computeSpectrum
  • When an image is being loaded in an HTML text field from another domain
  • When data will be directly loaded via API calls such as LoadVars, URLLoader, or XML.load by another domain
  • When import loading a remote SWF
  • When a web administrator wants to explicitly block all cross-domain loading requests to their site
  • When a SWF on a remote HTTP server needs to load data from within an HTTPS protected section of the server's website
It is not necessary to use a crossdomain.xml file:
 
  • When an image or SWF from another domain is loaded for presentation as a child without accessing anything inside of it (content loading)
  • When displaying or playing data from an RTMP server without trying to access video data or sound spectrum data
  • When loading an image from the same domain as the loader
  • When loading a remote SWF file, since cross-domain permissions for SWF-to-SWF communication are governed by other controls such as Security.allowDomain() or shared events
In order to successfully load remote content into a SWF file, a remote domain has to place a crossdomain.xml file in the directory of the content or one its parent directories. Before making a request to a new remote domain, Flash Player will verify that the settings to allowNetworking permit access to remote domains. Next, Flash Player needs to request the crossdomain.xml file to determine whether the current domain is allowed to load the remote domain's content. If the current domain is not listed in the crossdomain.xml file or the file does not exist, then access to the content is denied and an exception will be thrown when you attempt to access the data.
 
Cross-domain files can be used to explicitly deny access globally. If a cross-domain file is not present, then access is also denied. Access will also be explicitly denied to everyone by creating a crossdomain.xml file with no entries in the root directory and a site-control policy set to none:
 
<?xml version="1.0"?> <!DOCTYPE cross-domain-policy SYSTEM "/xml/dtds/cross-domain-policy.dtd"> <!-- Policy file for mysite.com --> <cross-domain-policy> <!-- No one can have raw access to any of the content on this site through Flash Player --> <!-- This is the only cross-domain policy file on this server --> <site-control permitted-cross-domain-policies="none" /> </cross-domain-policy>
 
The risks associated with cross-domain requests
There are several risks associated with cross-domain policy file requests. For example, assume that www.example.com uses cookies to track authentication and authorization to sensitive areas of their website. The administrators of the website have installed a cross-domain policy that allows all sites access by setting the allow-access-from domain setting to a global wildcard ("*"). The impact of this setting is that the website is informing Flash Player that the same-origin restrictions do not apply to their site. Therefore, a malicious SWF from a remote domain is now allowed access to all of the data and content within www.example.com. Since the web browser will append any existing cookies to HTTP requests made by Flash Player, the SWF from the remote domain could make requests to areas of the website that contain sensitive information. The malicious SWF can then take the data returned within the response and forward it back to their original website.
 
This threat can be expanded if the overly permissive cross-domain file is on an internal network. For instance, an internal IT person may create a cross-domain file with a domain="*" setting thinking that the host is on an internal network and everyone is trusted on the internal network. However, cross-domain policy files are a way for hosts to state which domains the host trusts with its data. Therefore, the IT administrator's cross-domain policy file states that the internal host trusts all sites with its data including Internet sites. Therefore a SWF loaded by the browser from an external website would be allowed to make requests to the internal website and relay that information back to the Internet.
 
 
Refining access with cross-domain
Due to the many risks associated with cross-domain permissions, there are several controls available to an administrator to grant granular permissions to their content. These controls include:
 
  • Placing sharable content on one sub-domain (public.mysite.com) and non-sharable content on another sub-domain (private.mysite.com)
  • Using wildcards in conjunction with static domain information to limit the scope of the permissions
  • Granting permissions based on sub-directory
  • Using meta-policies to prevent unapproved cross-domain policy files
  • Granting permissions only to SWFs loaded over HTTPS
The next few sections detail these techniques for avoiding creating overly permissive cross-domain permissions.
 
 
Using wildcards in conjunction with domain names
If the domain has multiple sub-domains that change frequently, administrators can use a wildcard in conjunction with the parent domain name by specifying domain="*.mysite.com" instead of domain= "*". Below are additional sample valid entries for a crossdomain.xml file that demonstrate alternatives to using the "*" wildcard:
 
<?xml version="1.0"?> <!DOCTYPE cross-domain-policy SYSTEM "/xml/dtds/cross-domain-policy.dtd"> <!-- Policy file for mysite.com --> <cross-domain-policy> <!-- This is the only cross-domain policy file for this server --> <site-control permitted-cross-domain-policies="master-only"/> <!-- Administrators can set multiple entries with a wildcard on the sub-domain to avoid setting domain="*" --> <allow-access-from domain="*.mysite.com" /> <allow-access-from domain="*.myothersite.com" /> </cross-domain-policy>
However, there are still some risks associated with this approach. If the site you are granting access to allows users to upload content to a sub-domain of their website, such as uploads.example.org, then a "*.example.org" permission would allow the end-user content to access your site as well. Depending on the permissions you are granting, allowing arbitrary third-party data that is hosted on uploads.example.org may be an unnecessary security risk. It is important that you thoroughly understand what type of content is hosted on the site to which you are granting access.
 

 
Always using SSL consistently

 
Related threats: Unauthorized access to data in transit
Flash Player version 7 and later have several restrictions preventing HTTP loaded SWFs accessing resources served over HTTPS. These restrictions are in place by default to prevent untrusted SWF files loaded over HTTP from accessing sensitive data that was securely communicated to trusted SWF files loaded over HTTPS. SWF files loaded over HTTP are untrusted because they are subject to man-in-the-middle attacks. A man-in-the-middle attack is where someone sitting on the network between the end-user and the server alters or replaces the SWF file while it is in transit. Man-in-the-middle attacks are frequently executed in places such as wireless networks.
 
Some websites create SWF applications which load all of their data over HTTPS in order to ensure that the data is protected. However, problems occur when these websites start the user experience by loading the initial SWF application over HTTP. For the end-user, Flash Player does not provide feedback that the Flash application is using HTTPS so the end-user can not validate their information is being protected. Also, since the initial Flash application is loaded over HTTP, it is subject to a man-in-the middle attack and therefore the end-user can not trust the SWF file. If SSL is going to be used to protect data, then it should be used consistently throughout the entire application. This will ensure that the user receives the SWF over a secure connection and it will aid the developer in avoiding issues created by mixing insecure and secure protocols.
 
 
Avoid allowing HTTP and HTTPS SWF files to communicate
It is possible to override these protections by setting the secure flag for the domain to "false" within the crossdomain.xml file. This practice is not recommended. For instance, you would probably not feel comfortable if unsecured HTTP content from your bank's website was able to reach into your secured connection with your bank to extract information. If allowing communication from HTTP SWF files to HTTPS protected data is absolutely necessary, try to limit the exposure of the HTTPS protected data to the HTTP loaded SWF file. For instance, you would want to avoid setting the secure flag to "false" for the entire website and instead place the cross-domain permission in a specific sub-directory. If you need to allow HTTP-loaded SWF files to communicate with HTTPS-loaded SWF files, then a cross-domain policy file with a secure flag of "false" is not necessary because cross-domain policy files do not govern SWF-to-SWF communication.
 
 
Insecure HTTPS connections
Flash Player supports making HTTPS requests by using the browser's SSL implementation. Therefore if a SWF is connecting to a server with certificates issues such as an expired certificate or a failed domain name match, then the browser will handle prompting the user about issue. Developers should work with website administrators to ensure that SSL certificates are current, signed by a trusted Certificate Authority and match the host's domain name in order to provide the user with a secure and seamless experience.
 
 
Ensuring SSL protections with the secure flag
By default, the crossdomain.xml file will prevent SWFs hosted on an HTTP server from accessing data served from an HTTPS protected site through the use of the secure flag. The default value of the secure flag is "true" which informs the player not to allow remote HTTP loaded SWF files from accessing content on the HTTPS protected areas of the website. Transmitting data that was originally protected by SSL to a remote server over HTTP can defeat all the protections that the SSL connection originally provided for that data.  The secure flag can be applied to either web or socket policy entries.
 
<?xml version="1.0"?> <!DOCTYPE cross-domain-policy SYSTEM "/xml/dtds/cross-domain-policy.dtd"> <!-- Policy file for mysite.com --> <cross-domain-policy> <!-- This is a master-policy file --> <site-control permitted-cross-domain-policies="master-only"/> <!-- This says that http://www.mysecuresite.com can access this site's HTTP data --> <!-- SWFs on https://www.mysecuresite.com can access this site's HTTPS data --> <!-- SWFs on http://www.mysecuresite.com can not access this site's HTTPS data --> <allow-access-from domain="www.mysecuresite.com" secure="true" /> </cross-domain-policy>
 
Understanding ports vs. protocols
The secure flag within the cross-domain policy file tells Flash Player whether it should prevent cross-protocol communication between HTTP and HTTPS for the domain listed in the allow-access-from tag. It does not tell Flash Player to acknowledge any given port. Cross-domain policy files do not include the ability to restrict access based on the source port of the connection. If the cross-domain policy file allows access from www.example.org, then it will allow access to any SWF that was loaded over HTTP, whether or not the SWF was loaded from a server www.example.org:80 or a server listening on www.example.org:8080. If the above cross-domain policy file were hosted on https://www.mysite.com:8443/, then the secure flag would tell Flash Player that a SWF loaded from http://www.mysecuresite.org:8080/my.swf could not load its content because the SWF was loaded via a different protocol from the website.
 
Flash Player does pay attention to the port number of the server that is hosting the cross-domain policy file. If a web server has a policy file hosted on http://www.example.org:80/crossdomain.xml, then that policy file would not apply to the web server hosted on http://www.example.org:8080/. A separate cross-domain policy file would need to exist on the www.example.org:8080 website if that site wanted to permit other domains access to its content.
 
 
Allowing custom headers
Starting with Flash Player 9,0,124,0, Adobe introduced the capability to define which custom headers Flash Player can send across domains. These settings are defined by the allow-http-request-headers-from tag within the cross-domain file. Similar to other elements within the crossdomain.xml file, it is possible to set the domain attributes describing the sites that are allowed to forward headers using the full domain name of the remote domain, a wildcard, or a combination of the two. In addition, the secure attribute maintains the same meaning as it has within the allow-access-from described above. The headers attribute is where it is possible to define which headers are allowed to be sent to the domain hosting the cross-domain policy. Although wildcards are supported, we recommend that only the specific headers that are intended to be accepted be specified:
 
<?xml version="1.0"?> <!DOCTYPE cross-domain-policy SYSTEM "/xml/dtds/cross-domain-policy.dtd"> <cross-domain-policy> <!-- This domain can accept the HTTP Request headers MyHeader and MyOtherHeader from a SWF file on www.example.com --> <allow-http-request-headers-from domain="www.example.com" headers="MyHeader,MyOtherHeader" secure="true"/> </cross-domain-policy>

 
Complex cross-domain implementations

The following sections discuss more complex, cross-domain implementations, including cross-domain policy files in sub-directories, utilizing meta-policies, and socket policy files.
 

 
Utilizing crossdomain.xml in subdirectories

If you'd like to get more information about how to work with the loadPolicyFile method, see loadPolicyFile() in the ActionScript 3.0 Language and Components Reference.
 
HTTP policy files can be specified from subdirectories in order to define access for that directory and all of its subdirectories. Therefore, rather than creating a very general crossdomain.xml file in the root directory of a site, an administrator can allow users to define their own crossdomain.xml files within their subdirectories for their specific needs. For instance, a developer who needs to specify domain="*" can specify that permission in a sub-directory crossdomain.xml file to expose only that directory as an alternative to placing domain="*" in the root crossdomain.xml file. This may be useful in situations where a developer creates local-with-networking SWF files which require a domain="*" setting to communicate with a public website. Crossdomain.xml files hosted from a subdirectory can not define access to ports.
 
The following code example illustrates how to load a policy file from a subdirectory:
 
//Load a policy file which allows cross-domain access to the ~user1 directory System.security.loadPolicyFile("http://www.example.com/~user1/myPolicy.xml"); //Access data under the ~user1 directory NetStream.play("http://www.example.com/~user1/vids/myVideo.flv");

 
Avoid using FlashVars in loadPolicyFile() calls

 
Related threats: Cross-site request forgery
Developers should avoid obtaining URLs from FlashVars for use in the loadPolicyFile method. If the attacker can control the FlashVar, then they can use the loadPolicyFile method to make a cross-domain GET request and send arbitrary data to a remote site. This could result in an unauthorized information disclosure or a cross-site request forgery attack. If a developer must accept the location as a FlashVar, then the developer should takes steps to make sure that the URL is on an approved whitelist before providing the URL to the loadPolicyFile method.
 

 
Meta-policies can be used to control sub-domain crossdomain.xml files

For more information on meta-policies, please see Policy file changes in Flash Player 9 and Flash Player 10: Meta-policies.
 
Allowing any user on a system to create a crossdomain.xml file for their directory is of frequent concern to many system administrators. In some instances, system administrators want to be the only entity capable of defining cross-domain permissions. Starting with Flash Player 9 Update 3, Flash Player acknowledges controls set by the system administrators to limit which directories are allowed to create crossdomain.xml files. These options that are specified within a <site-control/> directive include:
 
  • none: No policy files are allowed anywhere on the server, including the master policy file. Any allow-access-from information included after the meta-policy will be ignored.
  • none-this-response: This is a special meta-policy that can only be specified in an HTTP response header. It prevents this particular HTTP response from being interpreted as a policy file. Unlike all other meta-policies, none-this-response affects only a single HTTP response, rather than declaring an overall meta-policy for the entire server. Also unlike all other meta-policies, none-this-response can appear in combination with any other meta-policy without conflict. When none-this-response and another meta-policy are both present, then the current HTTP response will not be allowed to be a policy file, but the additional meta-policy will be interpreted to be the overall meta-policy for the server.
  • master-only: Only the master policy file located at /crossdomain.xml is allowed. This is the default setting for Flash Player 10 and later.
  • by-content-type: This setting is available only for HTTP and HTTPS servers. Only policy files served with the header Content-Type: text/[x-]cross-domain-policy are allowed.
  • by-ftp-filename: This setting is available only for FTP servers. Only policy files whose URLs end with /crossdomain.xml are allowed and no other policy files are allowed.
  • all: All policy files are allowed. This setting should only be used on public Internet servers that do not require login credentials. This is the current setting within Flash Player.
To utilize these controls, an administrator would create a crossdomain.xml file similar to the following example in their root web directory:
 
<?xml version="1.0"?> <!DOCTYPE cross-domain-policy SYSTEM "/xml/dtds/cross-domain-policy.dtd"> <!-- Policy file for mysite.com --> <cross-domain-policy> <!--This is the only cross-domain policy file for this server --> <site-control permitted-cross-domain-policies="master-only"/> </cross-domain-policy>
Alternatively, you can specify meta-policies within HTTP response headers. With the header mechanism, the meta-policy must be declared in every HTTP response. Meta-policies can be declared using the X-Permitted-Cross-Domain-Policies header, as follows:
 
HTTP/1.1 200 OK X-Permitted-Cross-Domain-Policies: none
This mechanism for meta-policies is not valid for FTP servers. If the none-this-response policy is being applied, then it may be necessary to send two policies. You can do this either by returning two headers or by using one header, separating the policies by a semicolon.
 
The meta-policy implementation is being back-ported to Flash Player 7 and Flash Player 8 to reach as many end-users as possible.
 

 
Initiating a policy file check

If you'd like to research the content discussed in this section further, you may find it useful to visit the following sections of the ActionScript 3.0 Language and Components Reference:
 
You can use the checkPolicyFile property to check for a policy file. There are checkPolicyFile properties for NetStream, SoundLoaderContext, LoaderContext and image tags in an HTML text area. This property is applicable to the Loader.load() method, but not to the Loader.loadBytes() method.
 
Set this property to true when you are loading an image (JPEG, GIF, or PNG) from outside the SWF file's domain, and you need programmatic access to the content of that image using ActionScript. Flash Player will first consider policy files that have already been downloaded, next it attempts to download any pending policy files specified in calls to the Security.loadPolicyFile() method, and then attempts to download a policy file from the default location that corresponds to URLRequest.url, which is /crossdomain.xml on the same server as URLRequest.url.
 
An example of accessing image content involves referencing the Loader.content property to obtain a Bitmap object, and calling the BitmapData.draw() method to obtain a copy of the loaded image's pixels. Attempts to utilize one of these operations without specifying a checkPolicyFile at loading time may result in a SecurityError exception because the needed policy file has not been downloaded yet.
 
The code example below illustrates how to check for policy files to avoid security errors:
// Setting a Loader to check the policy files var ldr:Loader = new Loader(); var loader_context:LoaderContext = new LoaderContext() loader_context.checkPolicyFile = true; var url:String = "http://www.remote_example.com/content.swf"; var urlReq:URLRequest = new URLRequest(url); ldr.load(urlReq,loader_context); // Checking for a policy file by specifying "CheckPolicyFile" in an // image tag defined within a TextArea <img src = 'http://remote.server.org/filename.jpg' checkPolicyFile = 'true' id = 'instanceName' >
SWF files are unable to check for cross-domain files if the allowNetworking parameter of the object and embed tags is set to false. If a SWF cannot locate the policy file, then a SecurityException will be thrown at the time a data load is attempted.
 

 
Socket policy files

 
Related threats: DNS rebinding, cross-domain privilege escalation
This section provides a brief summary of socket policy files. For complete information on socket policy files, please see Policy file changes in Flash Player 9 and Flash Player 10: Socket policy files and Setting up a socket policy server.
 
Socket policy files define what socket connections are permitted to the domain. Flash Player prevents attacks such as DNS rebinding by requiring the destination IP address to authorize the connection. In order to make a socket connection, Flash Player must first find a master socket policy file server listening on port 843 or a policy from the same port as the intended connection. Like master cross-domain policy files, master socket policy files support meta-policies to define where policy files are allowed on the server. The available meta-policies are:
 
  • all: Socket policy files are allowed from any port on this host. This meta-policy is appropriate only for hosts that are on the public Internet and do not serve any content that requires login credentials. This is the default.
  • master-only: Only the socket master policy file, served from port 843, is allowed on this host. The master socket policy file will define all of the allowed ports.
  • none: No socket policy files are allowed on this host. If this meta-policy is declared in the master policy file, then the master policy file is permitted to exist solely for the purpose of declaring this meta-policy, and any <allow-access-from> directives that it contains will be ignored.
If you specify a meta-policy of master-only, then all of the port permissions must be defined within the master socket policy file; any additional policy files that are loaded via loadPolicyFile() call will be ignored. If you specify a meta-policy of all, then this will allow you to host additional socket policy files on ports other than 843 or the destination socket. These socket policies can grant access to additional ports on the machine. However, there is one additional restriction: Policy files hosted on ports greater than 1024 can grant access only to other ports above 1024. A policy file returned from a port less than or equal to 1024 can allow access to any port. For instance, the master socket policy file is hosted from port 843 and can therefore allow access to all ports on the server.
 
 
Setting the secure flag
Socket policy files support a secure flag that is similar to HTTP policy files. Setting this flag to "true" within an <allow-access-from> directive informs Flash Player that only SWF files served over HTTPS are allowed to connect to the specified port. By default this flag is assumed to be false. It is currently not a best practice to rely on this flag for remote sockets since socket policy files are currently fetched over insecure protocols and are subject to man-in-the-middle attacks. Therefore, an attacker may change the value of the flag while it is transit. This flag may be appropriate for localhost connections where man-in-the-middle attacks are far less likely.
 
 
Use ranges and commas in a socket policy file to define port access
Instead of using wildcards to define port access, Flash Player will accept ranges and commas to specify groups of port numbers. This can reduce the risk of accidentally exposing non – Flash Player related ports to Flash Player's socket libraries:
 
// Use an XMLSocket request to port 843 in order to download a policy // file allowing access to 456 System.security.loadPolicyFile("xmlsocket://socks.mysite.com:843"); // Connect to port 456 mySocket.connect("socks.mysite.com", 456); // The crossdomain.xml file on port 123 allowing access to 456 <?xml version="1.0"?> <!DOCTYPE cross-domain-policy SYSTEM "/xml/dtds/cross-domain-policy.dtd"> <!-- Policy file for xmlsocket://socks.mysite.com --> <cross-domain-policy> <!-- This is a master-policy file --> <site-control permitted-cross-domain-policies="master-only"/> <!-- Instead of setting to-ports="*", administrator's can use ranges and commas --> <!-- This will allow access to ports 123, 456, 457 and 458 --> <allow-access-from domain="socks.mysite.com" to-ports="123,456-458" /> </cross-domain-policy>

 
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 }

 
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.
 

 
Validating data from remote sources

Flash Player can import data through networking APIs and FlashVars. A common mistake that developers make is to assume that the only way that a SWF will accept FlashVar data is through the FlashVars param tag within an object tag. SWF files that accept FlashVars will actually read in data through two methods. In addition to the FlashVars attribute, SWF files can also read in variables from:
 
http://www.mydomain.com/mySWF.swf?variable_name=variable_value
In an ActionScript 2.0 SWF file, any uninitialized variable can be initialized as a FlashVar. This can cause issues for developers if they forget to initialize a key variable or they assume that their code will initialize the variable first. These attacks were documented as early as 2002 with the EyeOnSecurity paper, The Flash Attack. In ActionScript 3.0, all FlashVars can only be accessed via the LoaderInfo class and all variables must be initialized.
 
When validating data, there are a few key points to consider for most types of data:
 
  • Is the data the correct length? If a variable length is allowed, compare the data against both the minimum and the maximum allowed length.
  • Does the data contain the correct characters? For ASCII characters, create a whitelist of allowed characters for that data. When dealing with Unicode and Internationalization, it may be necessary to do a blacklist approach.
  • Are the characters in the correct order? For instance, you may allow parenthesis in a phone number. However, you should also validate that the parenthesis are in first and fifth position in the string. Therefore the string "1(23-497-8890)" should be rejected.
  • If the data is a set of logical blocks, are the individual blocks the correct length and format? For instance a social security number is a set of digits grouped in a 3-2-4 format and a US phone number is a set of digits grouped in a 3-3-4 format.
  • Does the data contain only the expected strings? Does the data contain any unwanted strings? For instance, you may not want your URL to contain unwanted schemes such as javascript:. Therefore you should validate that the URL string starts with http:// or https://.
FlashVars are not the only way to import dynamic data. If allowNetworking is not set to "none" within the object tag, then developers can use LoadVars/LoadVariables (in ActionScript 2.0), XML classes, or other loaders to obtain data from the server. FlashVars are subject to malicious initialization from the URL. Loading remote data from a trusted source may be subject to network based attacks such as man-in-the-middle attacks if SSL is not used. In either case, data validation should be performed.
 
 
Third-party libraries can provide RegEx capabilities for ActionScript 2.0
A common technique for validating imported data is to check if the data matches a regular expression. ActionScript 3.0 provides native support regular expressions. Legacy ActionScript 2.0 developers must utilize third-party libraries, such as as2lib on SourceForge, in order to leverage regular expressions for data validation.
 
 
Free SDKs provide common data validation classes
Fully developed data validation libraries can be found on the Internet, such as the flash-validators project on Google Code. Adobe Open Source also provides sample data validation libraries within the free Flex 3 SDKs.
 

 
Accepting URLs for remote content as parameters to the SWF file

 
Related threats: Cross-domain privilege escalation, malicious data injection, script injection into the browser
It is critical to perform data validation on the variables provided in URLs or FlashVars because SWF files that can accept URLs as dynamic variables are susceptible to several types of attacks if data
 
 
Attacking methods that communicate with the browser
One of the most prevalent mistakes is accepting variables via FlashVars or URLs and passing them directly to a function that communicates with the browser such as getURL() or navigateToURL().
 
As an example, consider the following ActionScript 3.0 code:
 
try { var url:String; var paramObj:Object = LoaderInfo(this.root.loaderInfo).parameters; url = String(paramObj["url"]); } catch (error:Error) { trace(error); } var request:URLRequest = new URLRequest(url); navigateToURL(request,"_self");
This code is taking a variable from either the FlashVars param tag or the URL string and passing it directly to a load request without validating that the value being passed is the expected value. Since the request is being passed directly to the browser, the attacker can pass any protocol that the browser accepts. Therefore, if an attacker were to send the following request:
 
http://www.example.com/example.swf?url=javascript:alert(document.cookie)
The request above would permit an attacker to cross-site script into the example.com domain. The result of this particular attack will vary based on the browser hosting the SWF file but the concept will still apply. As a real-world example, this attack was used against ActionScript 2.0 clickTAG marketing advertisements in 2004 (see the following TechNote: Privacy and Flash ad tracking).
 
There are several strategies you could use to protect against this type of attack. For instance, if the you plan on only requesting URLs from your own domain then you could replace the URLRequest initialization in the risky example noted above with this line of code instead:
 
// Be careful using this if your site has open redirectors var request:URLRequest = new URLRequest("http://www.example.com/" + url);
Another technique that you can use when data must be loaded from arbitrary domains is to perform data validation on the URL by denying any URL that does not begin with http:// or https://. Therefore the following code could be used to do basic tests of the URL before using it. For enhanced security, it may be prudent to do more thorough checks than this simple example such as validating the URL does not contain any special characters:
 
// AS3 Regular expression pattern match for urls that start with // http:// and https:// plus your domain name. function checkProtocol (flashVarURL:String):Boolean { // Get the domain name var my_lc:LocalConnection = new LocalConnection(); var domainName:String = my_lc.domain; // Build the RegEx // This RegEx assumes that there is at least one "/" after the // domain. http://www.mysite.com will not match. var pattern:RegExp = new RegExp("^http[s]?\:\\/\\/([^\\/]+)\\/"); var result:Object = pattern.exec(flashVarURL); if (result == null || result[1] != domainName || flashVarURL.length >= 4096) { return (false); } return (true); } // For AS2 coders, this is an example without regular expressions: // The comparison can be adjusted to include both the protocol and your // domain name for added security. // checkProtocol returns true if the protocol is allowed function checkProtocol(url:String):Boolean { var my_lc:LocalConnection = new LocalConnection(); var domainName:String = my_lc.domain(); // Is the URL the correct length? if (url.length < 7 + domainName.length || url.length > 4096) { return false; } // Reject any URL that uses a protocol other than http: or https // Also verify the URL is for my domain if (url.substr(0,8 + domainName.length) == "http://" + domainName + "/" || url.substr(0,9 + domainName.length) == "https://" + domainName + "/") { return (true); } else { return (false); } } // AS3 Regular Expression for matching an URL with an IP address var pattern2:RegExp = /^http[s]?\:\/\/([1]?\d\d?|2[0-4]\d|25[0-5])\.){3}([1]?\d\d?|2[0-4]\d|25[0-5])\// // AS2 Function for validating a URL function isIpUrl (myIP:String):Boolean { var myArr:Array = myIP.split("."); if (myArr.length != 4) {return(false);} for (var i:Number = 0; i < myArr.length; i++) { var temp:Number = parseInt(myArr[i]); if (temp == NaN || (temp < 0 || temp > 255) || (temp == 0 && i == 0)) { return (false); } } return (true); }
If the SWF file is only using the URL for networking requests, then these techniques for protecting the SWF file could be coupled with setting the allowScriptAccess param tag to never in the HTML to ensure that scripting actions are not sent to the browser. This has the added protection of not only ensuring the loading SWF does not send scripting actions to the browser but also ensuring that any SWF loaded by the parent does not send scripting actions to the browser.
 
 
Sending data via navigation functions
More information on the ActionScript 2.0 getURL() function can be found in the ActionScript 2.0 Language Reference.
 
Some developers will set the method to "GET" or "POST" within the third parameter of the getURL() function. This will append the variables within the SWF to the request as either GET parameters on the URL or as a header when using POST. Developers should do testing to ensure that no unexpected data is sent with these requests since ActionScript 2.0 does not provide a way to specify which variables are sent. In addition, this functionality should be used with caution when setting the GET method since the data will be appended to the end of the URL. If the URL is a javascript: URL, then appending untrusted data could result in arbitrary JavaScript execution. With ActionScript 3.0, you must manually specify the variables you want associated with a request so there is not the same risk with accidentally including unwanted variables.
 
 
Escaping special characters
The functions described here are core ActionScript 3.0 classes. Please refer to the global functions in the ActionScript 3.0 Language and Components Reference.
 
Flash Player provides several functions for escaping characters in URIs. Escaping characters can help ensure that your code creates valid URLs. These functions include escape, unescape, encodeURI, decodeURI, encodeURIComponent, and decodeURIComponent. Determining which function is appropriate will depend on the data you are working with and whether the data represents the entire URI or a smaller component. One example of a possible attack would be a user injecting "&evil_var=evil_value" onto the end of a URI where evil_var has meaning to the target application. Another example would be an attacker injecting malicious data onto the end of a file: URL in attempt to manipulate the OS. By encoding or escaping the data, a developer can reduce the possibility of these attacks succeeding on the target web server:
 
function sendDataToServer (userSuppliedData:String) { myURL:String = "http://www.mysite.com/cgi-bin/recieve_data.cgi?myvar="; myEscapedData:String = escape(userSuppliedData); sendToURL (myURL + myEscapedData); }
 
Validate URLs sent to networking functions
The aforementioned techniques should also be applied to networking functions. URLs should always be validated whenever they are used to load XML data or variables from a remote resource. For instance, a SWF may accept a FlashVar URL as a pointer to its configuration file. If an attacker can redirect the SWF to loading from another domain, then the SWF could be
 
It is also a bad practice to dynamically accept URLs that are passed to the loadPolicyFile function. The loadPolicyFile function can be misused as a method for sending a cross-domain HTTP GET request as part of a cross-site request forgery attack. Once Flash Player receives bad return data from the initial request, subsequent requests to that area of the site will be blocked.
 

 
Safely loading remote variables and data

 
Related threats: Malicious data injection
Variables are commonly loaded in from some of the following APIs:
 
  • loadVariables, loadVariablesNum, MovieClip.loadVariables, LoadVars.load, LoadVars.sendAndLoad
  • XML.load, XML.sendAndLoad
  • URLLoader.load, URLStream.load
  • LocalConnection
  • ExternalInterface.addCallback
  • SharedObject.getLocal, SharedObject.getRemote
Whenever data is retrieved from a remote resource, the developer should take measures to validate the data before processing it. This can include when the SWF is accepting data from the browser via ExternalInterface.addCallback, loading data from a remote socket via XML loading operations or loading variables from a LoadVars or LoadVariables method.
 
For instance, developers might assume that since they are loading from a trusted remote domain that the data is safe. However, if the data is served over HTTP then it can be subject to man-in-the-middle attacks where a third party tries to change the data in transit. When considering what level of protection is appropriate, the developer should take into account the value of the data of the hosting page. For instance, if the SWF has a cross-site scripting vulnerability, then it is the hosting page that is compromised and it is the user's data on that site at risk.
 
The following example demonstrates a very basic validation function. In most instances, the developer will want to augment these examples to be more specific to their environment:
 
// AS3 Example function validHex(hexString:String):Boolean { // This will validate a string that is only 6 hex characters. var pattern:RegExp = /^[A-Fa-f0-9]{6}$/ // Test the string against the pattern in if (!pattern.test(hexString)) { return (false); } return true; } // AS2 Example // Validate that hexString contains only 6 hex characters function validHex (hexString:String):Boolean { var hexChars="0123456789ABCDEFabcdef"; // Validate that it is the expected length if (hexString.length != 6) {return(false)}; // Validate that it contains the expected characters for (var i=0; i<hexString.length; i++) { if (hexChars.indexOf(hexString.charAt(i)) < 0) { return(false); } } return (true); }
When the SWF is receiving data from the browser, the registered callback function should validate the data that is received. Even if the SWF is hosted by a trusted site, there is the possibility that the hosting site has a cross-site scripting vulnerability that is allowing an outside attacker to make arbitrary JavaScript calls. Therefore, all data from external sources should always be validated.
 

 
Safely displaying content in text fields and drawable regions

This section describes how to securely display data within your SWF application. I discuss working with HTML formatted text fields as well as loading content into drawable regions.
 

 
Using output validation to protect HTML text fields

 
Related threats: Malicious data injection, script injection into the browser
If you'd like to learn more about working with HTML formatted text, refer to htmlText in the ActionScript 3.0 Language and Components Reference.
 
A Flash Player text field can display HTML formatted text via the htmlText property of a TextField in ActionScript 3 or if the html property of a TextArea in ActionScript 2.0 is set to true. Flash Player supports a subset of HTML tags that include formatting, image, and anchor tags. Security vulnerabilities can occur when unverified data is taken from an external resource and placed within the text field. Since the HTML is interpreted, the field can be subject to common web attacks such as cross-site scripting. Therefore, it is a best practice to use regular text fields whenever possible.
 
In some instances, you may encounter a valid need to create an HTML text field that displays content from third-party sources. Output validation can be used as a defense-in-depth measure to ensure that unwanted HTML is not injected within the text field. This is a common technique that is also used by web server applications to prevent cross-site scripting attacks. In ActionScript 3.0, Adobe improved the String class to include replace methods. There are several documented techniques on the web for implementing search and replace methods in ActionScript 2.0.
 
The following examples demonstrate methods for replacing characters in both languages:
 
// AS3 Example Using Regular Expressions // Replaces an individual character in a string function replace_char (oldChar:String, newChar:String, origString:String):String { var matchOld:RegExp = new RegExp(oldChar,"g"); var tempString:String = origString.replace(matchOld,newChar); return (tempString); } // Replaces an array of characters within a string function replace_group (replaceArray:Array,myString:String):String { var newString:String = myString; for (var i:Number = 0; i < replaceArray.length; i++) { var charArray:Array = replaceArray[i].split("|"); newString = replace_char(charArray[0],charArray[1],newString); } return (newString); } // A pipe delimited array of replacement pairs var replaceArray:Array = ["&|&amp;","<|&lt;",">|&gt;","\"|&quot;","'|&apos;"]; // Replace all HTML tags with HTML encoded characters within the string var safeString:String = replace_group(replaceArray,stringWithHTML); // AS2 Example Using String Methods function escapeHTML(str:String):String { var safeString:String = str; if (safeString.indexOf("&")>=0) { safeString = safeString.split("&").join("&amp;"); } if (safeString.indexOf("<")>=0) { safeString = safeString.split("<").join("&lt;"); } if (safeString.indexOf(">")>=0) { safeString = safeString.split(">").join("&gt;"); } if (safeString.indexOf("\"")>=0) { safeString = safeString.split("\"").join("&quot;"); } if (safeString.indexOf("'")>=0) { safeString = safeString.split("'").join("&apos;"); } return (safeString); }

 
Checking for invalid URLs before writing to an HTML text field

 
Related threats: Malicious data injection, script injection into the browser
In some instances, you may encounter a valid need to create an HTML text field that displays content from third-party sources. Malicious users can attempt to abuse this functionality by injecting cross-site scripting attacks through the use of javascript: or vbscript: URLs within the anchor and image tags. An attacker may also attempt to inject calls to the ActionScript code by inserting asfunction: or event: URLs within the HTML text field.
 
It should be noted that an attacker may attempt to inject a URL with any scheme. There are many, many schemes recognized by the web browser and therefore you will need to consider what risks their may be to your users and application if an unexpected scheme is injected. Any approach needs to address both anchor and image tag URLs. The following example demonstrates how to check a string for URLs that are typically used for cross-site scripting:
 
// Check for javascript:,event:,vbscript:,and asfunction: in a string // There are many schemes available that an attacker could inject // This only checks for protocols common to cross-site scripting // This is for when dynamically accept htmlText with links is required // Example for ActionScript 2.0 or ActionScript 3.0 function validHTMLString(htmlString:String):Boolean { // convert the string to lowercase since URLs are case insensitive var str:String = htmlString.toLowerCase(); // remove spaces, tabs and newlines since different browser and // OS combinations occasionally ignore these characters str = str.split(" ").join(""); str = str.split("\t").join(""); str = str.split("\n").join(""); str = str.split("\r").join(""); //Test for protocol strings if (str.indexOf("asfunction:") >= 0 || str.indexOf("javascript:") >= 0 || str.indexOf("event:") >= 0 || str.indexOf("vbscript:") >= 0) { return (false); } return(true); } if (validString(myHtmlString) == false) { //The string contains bad data //Shutdown or fail safe }
 
Perform data validation on ActionScript 2.0 format settings
The format settings for a text field are also translated into HTML. Therefore, an attacker may try to do injection attacks against end users with older versions of Flash Player into fields such as the TextFormat.font field in ActionScript 2.0.
 
 
Image URLs within HTML text fields maintain domain restrictions
It is also important to remember that images in HTML text fields are still subject to cross-domain restrictions. If you are going to be loading images from a separate domain, then it is possible to check for cross-domain permissions by specifying the checkPolicyFile flag in the image tag:
 
// Checking for a policy file by specifying "CheckPolicyFile" in // an image tag defined within a TextArea <img src='filename.jpg' checkPolicyFile='true' id='instanceName' >
Image tags within text fields can be used to load SWF files as well. In this instance, a Loader object will be used to instantiate the embedded SWF and the object can be retrieved through a getImageReference() call. Accessing the content of the remote SWF will still require Security.allowDomain() permissions.
 

 
Always set a mask for Loader objects

 
Related threats: Spoofing, cross-domain privilege escalation
If you'd like to access the full documentation for this topic, read about the DisplayObject mask property in the ActionScript 3.0 Language and Components Reference.
 
When you are loading a SWF file from an untrusted third-party source, it may be necessary to define a mask for the Loader object to prevent the loaded content from drawing over portions of the Stage that are critical to the parent. The mask attribute is an inherited property for the Loader Object, since it is a child of the Display Object class.
 
The following ActionScript 3.0 code demonstrates how to set the mask on the Loader object:
 
import flash.display.*; import flash.net.URLRequest; var rect:Shape = new Shape(); rect.graphics.beginFill(0xFFFFFF); rect.graphics.drawRect(0, 0, 100, 100); rect.graphics.endFill(); addChild(rect); var ldr:Loader = new Loader(); ldr.mask = rect; var url:String = "http://www.untrusted.example.com/content.swf"; var urlReq:URLRequest = new URLRequest(url); ldr.load(urlReq); addChild(ldr);

 
Exception handling

 
SecurityErrorEvents and errors
To find more details about errors and handling security error events, visit the following pages in the ActionScript 3.0 Language and Components Reference:
 
It is easy to forget to catch thrown exceptions. Or accidentally add code that doesn't do anything meaningful when the exception is caught. Flash Player throws several errors and dispatches many events that should not be ignored.
 
For example, a security error event can be triggered when communicating through asynchronous connections to external sockets, URLs, or files. These events are not always triggered when the connection is made. Error events can also be triggered when certain types of processing are attempted on the loaded external data.
 
It is important for developers to monitor the types of exceptions thrown by each method and to catch as many as possible. When security errors are caught, you should invoke a fail-safe mechanism and either terminate the action or exit the application gracefully. It is dangerous to ignore the exception and continue onward with the current code path in situations where security has been compromised and Flash Player is throwing security errors:
 
// register an event listener for SecurityErrorEvents function onSecurityError(e:SecurityErrorEvent):void { // Cross-domain error: Not allowed to connect to this resource. // Do a safe shutdown. } //Create a Socket testSocket = new Socket(); >// Register the event listener testSocket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecurityError); // Try to connect socket.connect(host, port);
 
Handling loading errors
One common mistake that people make with security error events involves the Loader class. A Loader can cause a security error event when executing the Loader.load() method. However, security error event listeners for Loaders must be registered with the loaderInfo instance and not with the Loader class. As an example:
 
// Create a loader var loader:Loader = new Loader; // Register the EventListener to the loaderInfo object loader.contentLoaderInfo.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorListener);

 
Encrypting data

Several strategies are available to encrypt data in SWF web applications. These strategies are discussed briefly below.
 

 
Hashing algorithms

 
Related threats: Unauthorized access to data in transit, unauthorized access to local data
To learn more about working with the hashing algorithms discussed in this section, see the as3corelib project page on Google Code, the Alchemy ActionScript 3 Crypto Wrapper library on Adobe Labs, and the Flex 3 SDKs on Adobe Open Source.
 
Hashing is a method for performing non-reversible encryption that transforms the original text into a unique string, or hash. Since the hash is non-reversible, there is no method for converting the hash back into the original text. These algorithms are useful for handling processes such as password authentication and storage. In many applications, passwords are processed through a hashing algorithm and then the resulting hash is stored on disk. When an end-user authenticates to an application, a hash of the supplied password is created to determine if it results in the same unique string as the stored password hash. If the two hashes match, then the user is granted access. This methodology allows administrators to store passwords in a non-plaintext format without the risk of the password being decrypted and stolen.
 
As one example, as3corelib started as an Adobe Labs project and is now part of the Google Code project. It provides several utilities for JSON, web services, and cryptography. The cryptography library includes methods for supporting SHA256, SHA224, SHA1, MD5, and the WSSEUsernameToken. Adobe recommends using SHA256 in place of SHA1 or MD5 whenever possible—due to known cryptographic attacks against the hashing algorithms. Corelib requires libraries from the free Flex 3 SDK to perform the base-64 encoding:
 
// Import the SHA256 library from CoreLib import com.adobe.crypto.SHA256; // Initialize the string that needs to be hashed var myString:String = "HashMe"; // Create a hex representation of the SHA256 Hash var hexHash:String = SHA256.hash (myString); // Create a base64 representation of the SHA256 Hash var base64Hash:String = SHA256.hashToBase64(myString);
In addition to as3corelib, the Flex 3 SDK includes a SHA256 implementation that is available to Flex developers.
 
Lastly, a project from Adobe Labs called Alchemy allows developers to port C applications to ActionScript. As an example of this functionality, a port of the OpenSSL library was created and is available from the Alchemy Libraries page. This port includes support for SHA, SHA2, and MD5, as well as a demo app demonstrating how to leverage them.
 

 
Symmetric and asymmetric ciphers

 
Related threats: Unauthorized access to data in transit, unauthorized access to local data
To get more details about working with the AS3Crypto Framework 1.3, see the as3crypto library page on Google Code. To get more details about working with the Adobe Alchemy ActionScript 3 Crypto Wrapper library, see the Alchemy Libraries page on Adobe Labs.
 
Symmetric and asymmetric ciphers are useful when you want to create a reversible encryption of data. Several implementations of symmetric and asymmetric ciphers written in ActionScript can be found on the web. These are useful to leverage but developers have to be aware that SWF files can be decompiled. Therefore the secret and private keys for these tools cannot be stored within the SWF file itself. At a minimum, symmetric secret keys and asymmetric private keys would have to be downloaded over a secure Internet protocol or generated by the SWF on the end-users machine to prevent exposure.
 
 
Threats to keys within SWF files
There are several threats with using symmetric and asymmetric secret keys within a SWF file. If the symmetric or secret key is stored in a shared object, then you would have to keep in mind that shared objects are non encrypted and can therefore be read by the user or by malicious software on the user's machine. Careful consideration should also be given to before making any changes to the default localPath setting since this will expand the number of SWF files that can read the data within the shared object. Setting the secure flag on the shared object to true can help limit the access to the shared object to securely loaded SWF files. A SWF file loaded over HTTP would be subject to a man-in-the-middle attack and, if an attacker successfully replaces the SWF file in transit, then the malicious SWF file could steal the key out of the Shared Object. External SWF files hosted on the same domain, that are import loaded into the encrypting SWF and any external SWF files that are granted permissions through the Security.allowDomain() settings, could also have cross-scripting permissions to obtain the key from the SWF file.
 
If you decide to use an asymmetric cipher, it is possible to safely store the public key within the SWF file. The public key can be used for encrypting data prior to sending it to a server application that has the corresponding private key. This approach allows one-way communication of encrypted data to the server and can also be used to verify digitally signed data sent from the server to the SWF file. One example where this would be useful is in situations where it necessary to collect sensitive data, such as a password, and send it to the server. Since the SWF file would contain the public key and the public key is only used for encryption, it would not matter if someone decompiled the SWF file to steal the key. The attacker could send malicious encrypted data to the server but the server programmer should perform data validation regardless of whether encryption was used.
 
There are performance considerations with using cryptography, so perform thorough testing if the cryptography will be used extensively. For instance, RSA encryption tends to be faster than RSA decryption. In many situations, it may be easier and safer to leverage the HTTPS protocol for sending encrypted data instead of performing the encryption within ActionScript code.
 
Support for AES and RSA can be found in several frameworks, including the Alchemy ActionScript 3 Crypto Wrapper library on Adobe Labs and the open-source AS3Crypto Framework.
 
The following sample code demonstrates using the RSA encryption algorithm to encrypt data using the open source AS3Crypto Framework library. The AS3Crypto Framework provides support for RSA, AES, 3DES, Blowfish, SHA, MD5, HMAC, and several other cryptographic solutions. This code is solely intended to demonstrate that public key crypto is possible with an open source solution.
 
Note: Adobe did not author the AS3Crypto library and is not responsible for its maintenance or development. Developers should choose a library that they trust and is appropriate for their needs.
 
import com.hurlant.crypto.rsa.RSAKey; import flash.utils.ByteArray; import com.hurlant.util.Hex; import com.hurlant.util.der.PEM; // The public key containing no spaces or carriage returns // An openssl public key generated by: // openssl rsa -pubout -in private_key.pem -out public_key.pem // should work for baseline testing var myPEMPublicKeyString = "-----BEGIN PUBLIC KEY-----{BASE64 DATA with no spaces or return characters}-----END PUBLIC KEY-----"; // Put data to be encrypted into a byte array var data:ByteArray = Hex.toArray(Hex.fromString("MyInputString")); // Destination ByteArray that will contain the encrypted data var encryptedResult:ByteArray = new ByteArray; // Set up the RSAKey and encrypt the data var rsa:RSAKey = PEM. readRSAPublicKey(myPEMPublicKeyString); rsa.encrypt(data, encryptedResult, data.length); // Convert the encrypted data into a hex encoded string for transport // The other side of the connection can convert the hex back into // binary before decrypting hexEncryptedResult = Hex.fromArray(encryptedResult);

 
Where to go from here

Deploying more secure SWF applications to end-users requires a coordinated effort from Adobe, Flash application developers, and website administrators. With each new release of Flash Player, Adobe strives to introduce a stronger platform with more robust security controls and tools for creating secure applications. By leveraging those tools, compiling for recent versions, performing data validation, and leveraging available SDKs, developers can produce more secure applications that run in Flash Player.
 
Website administrators can deploy these SWF files on their site by leveraging object tag parameters, appropriately deploying cross-domain policy files on their site and by working with developers on an agreed upon plan for access and deployment. By following these techniques, Flash Player applications can provide a rich Internet experience and a more secure environment for end-users.
 
Be sure to check out the following additional resources for further information on Flash Player security:
 
 
Adobe resources
 
Other resources

 
Developer checklist for writing more secure SWF applications

Data validation
 
  • Check for malicious URLs in all imported data
  • Escape special characters when writing into an HTML text field
  • Validate all data received from outside resources such as LocalConnections, LoadVariables, and XMLSockets
  • Use encrypted protocols where possible to prevent man-in-the-middle attacks
  • Check for returned exceptions as they may be an indication of malicious data
  • Be aware of situations where remotely loaded SWF files can script into your SWF and alter your variables and functions
  • Utilize ActionScript 3.0 rather than ActionScript 2.0 to prevent uninitialized variable attacks
Protecting sensitive data
 
  • Set the secure flag on local shared objects when using SWF files with SSL
  • Do not override the default path on the local shared object, or if it is necessary, set the path to the most restrictive path
  • Do not set the Secure flag to false within crossdomain.xml files
  • Do not use the allowInsecureDomain() method for SWF communication
  • Limit allowDomain() settings to specific domains
  • If SSL is used, use it consistently throughout the entire application workflow
  • Do not override the exactSettings setting in Flash Player
  • Leverage third-party libraries for additional cryptography
Cross-domain communication
 
  • Use specific domains in crossdomain.xml files
  • Leverage meta-policies to limit cross-domain and socket policies on your server
  • Do not use wildcards in domain or header settings within the cross-domain or socket policy file
  • Consider the most appropriate form of communication for the task at hand (i.e., a single method through LocalConnection vs. cross-scripting)
  • Use full domain names within allowDomain() settings
  • Be aware of the issues with import loading a SWF file into the current security domain via Loader.loadBytes or setting the securityDomain in LoaderContext
  • Do not override the exactSettings flag in Flash Player
  • Do not use unvalidated FlashVars as arguments to loadPolicyFile()
Preventing cross-site scripting attacks
 
  • Set appropriate allowScriptAccess and allowNetworking parameters within the HTML code
  • Perform data validation on variables sent to URL functions to ensure only http:// and https:// protocols are allowed; validate that the URL is for an allowed domain or use relative URLs
  • Escape special characters placed within HTML text fields
  • Do not use HTML text fields unless HTML support is needed
  • Compile the SWF for more recent Flash Player versions
  • Encourage users to have the latest version of Flash Player to view your content
Spoofing
 
  • Set masks on loaders for externally loaded SWF files.
  • Only allow trusted SWF files to use full-screen mode
Information Disclosures
 
  • Do not store sensitive encryption keys or passwords in a SWF file because it can be decompiled
  • Using the compiler flags such as "Protect From Import," "Omit Trace Actions," and "Permit Debugging" will not prevent determined attacks
  • Be aware that data stored in shared objects are also readable by third parties that have file system access since the data within the shared object is not encrypted
  • Use available cryptographic libraries when possible for encrypting data
  • Use an SSL connection consistently for more secure Internet communications

 
Website administration techniques for securing content

Explicitly set the allowScriptAccess, allowNetworking, and allowFullScreen settings for each SWF. By explicitly setting these values for all SWF files, administrators can ensure that the SWF files only have the access the administrator wants to grant and will not rely on Flash Player defaults for the compiled version when the SWF interacts within the web page.
 
Link to untrusted SWF files from your own domain by IP address rather than domain name. Referencing the untrusted SWF files by IP address will put them in a separate Flash Player security domain than the SWF files that are referenced by their domain name (e.g., http://1.2.3.4/my.swf does not have access to http://www.mysite.com/myOtherSWF.swf even though they are on the same server). Avoid using the IP address that is associated with your domain name via DNS.
 
Avoid specifying wildcards in cross-domain policy files. Use restrictive crossdomain.xml files for allowing access to only sites that are explicitly trusted. Limit the number of headers you accept only to those necessary for your application. Use wildcards on sub-domains such as *.mysite.com where possible avoid setting allow-access-from domain="*". Use commas ("456,457,468") and ranges ("456-458") on port settings to avoid setting to-ports="*" within the socket policy files.
 
Use sub-directory crossdomain.xml files to avoid putting domain="*" in the root crossdomain.xml file. By utilizing sub-directory crossdomain.xml files, web administrators can put domain="*" only in the parts of the website that really need to be accessible to all domains.
 
Utilize the meta-policy directives. The meta-policy system can help to ensure that only the cross-domain policies created by the administrator are recognized by Flash Player. Placing a master socket policy file with meta-policies on port 843 can help restrict what ports are allowed to host additional socket policy files. If no access is intended for your site then create an HTTP cross-domain file with a site-control meta-policy of "none" and no allowed domains listed. It is better to use the HTTP meta-policy of "by-content-type" than "all" for sites that contain multiple cross-domain policy files. If you select "all" and your site provides end-user upload functionality, then you should take into account the threat of end-users who will try to upload malicious cross-domain policies to your site.
 

 
Auditor checklist

If a SWF application has already been authored and it is now necessary to review the code looking for potential vulnerabilities, the methods listed below perform critical data operations that are useful to examine as part of your review process.
 
 
ActionScript 3.0 methods
Functions that display HTML code:
 
TextArea.htmlText
Functions that make networking calls:
 
FileReference.download(), FileReference.upload(), Loader.load, LocalConnection.connect(), NetConnection.connect(), NetStream.play(), Security.loadPolicyFile(), SharedObject.getLocal(),SharedObject.getRemote(), Socket.connect, Sound.load(), URLLoader.load(), URLStream.load(), XMLSocket.connect(), ExternalInterface.call(), navigateToURL(), sendToURL()
Functions and objects that accept URLs:
 
URLRequest(), NetConnection.connect(), XMLSocket(), XMLSocket.connect(), NetStream.play(), TextFormat.url, FLVPlayback.load(), FLVPlayback.play(), FLVPlayback.source, FLVPlayback.skin, FLVPlaybackCaptioning.source, ImageCell.source
Functions that perform content-loading:
 
Loader.load(),Sound.load(),Netstream.play()
Functions that communicate with the web browser:
 
ExternalInterface.call(), ExternalInterface.addCallBack(), fscommand(), navigateToURL()
Functions for accessing FlashVars:
 
LoaderInfo.parameters(), paramObj()
Functions for accessing SharedObjects:
 
SharedObject.getLocal(), SharedObject.getRemote()
 
ActionScript 2.0 methods
Functions and objects that accept URLs as strings:
 
MovieClipLoader.LoadClip, MovieClip.getURL(), getURL(), MovieCLip.loadMovie(), MovieClip.loadVariables(), NetConnection.connect(), LoadVars.load(), LoadVars.send(), LoadVars.sendAndLoad(), NetStream.play(), XML.load(), XML.send(), XML.sendAndLoad(), XMLSocket.connect, XMLSocket.send(), Sound.loadSound(), FileReference.download(), FileReference.upload(), System.security.loadPolicyFile(), LoadMovie(), LoadMovieNum(), loadVariables(), SharedObject.getRemote(), TextFormat.url
Functions that display or accept HTML:
 
TextField.html, TextField.htmlText, TextFormat.font
Functions that communicate with the web browser:
 
ExternalInterface.call(), ExternalInterface.addCallback(), fscommand(), getURL(), MovieClip.getURL()
Functions for accessing FlashVars:
 
_root., _level0. _global.
Functions for accessing shared objects:
 
SharedObject.getLocal(), SharedObject.getRemote()
Functions that make networking calls:
 
XML.load(), XML.send(), XML.sendAndLoad(), LoadVars.load(), LoadVars.send(), LoadVars.sendAndLoad(), loadVariables(), loadVariablesNum(), MovieClip.loadVariables(), NetConnection.connect(), NetStream.play(), loadMovie(), loadMovieNum(), MovieClip.loadMovie(), MovieClipLoader.loadClip(), Sound.loadSound(), LocalConnection.connect(), LocalConnection.send(), SharedObject.getLocal(), SharedObject.getRemote(), FileReference.upload(), FileReference.download(), System.security.loadPolicyFile(), XMLSocket.connect()
Generally risky:
 
eval()