I want to share it with you here in case your host also has mod_security installed.

Cross-domain data exchange in SWX back-story

securityIn SWX Beta 1, the way SWX Data SWFs handle allowDomain() has changed, although existing code will still work as it did.

Previously, if you enabled allowDomain in the SWX config file on the server (in other words, allowed cross-domain data exchange from your SWX gateway), the SWX Data SWFs would have a line in them that readSystem.security.allowDomain(_parent._url);. What this essentially means is: “Regardless of which domain I am loaded from, allow my parent SWF to have access to my contents.” That’s all fine and dandy but, due to the way sandbox security works, it meant that the parent SWF would also have to allow the SWX SWF access to itself (or else the SWX SWF would not be able to access _parent.) It’s all a little chicken and egg but the end result was that you were allowing the SWX SWF access to the main SWF and this was something I was not comfortable with (as it doesn’t need access to the main SWF for anything else.)

So, in Beta 1, I added a new way of achieving the same result that doesn’t require the main SWF to allow the SWX data SWF access to itself.

The new method for cross-domain data exchange in SWX Beta 1

Starting with SWX Beta 1, if you want to exchange data with your SWX gateway from different domains you have a new workflow available that involves two steps:

Firstly, you set the allowDomain option in the SWX configuration file to true. Secondly, you send an argument in your SWX call named url and set its value to _url (the URL of the calling SWF.) So, for example you could have a line of code that reads:

dataHolder.url = _url;

When using the Full API, this is handled for you.

When you do this, the resulting SWX data SWF will have a line in it that readsSystem.security.allowDomain('http://the.url.to.your/calling.swf');. As this does not access _parent, you do not need to allow the SWX data SWF access to the main movie.

This new workflow does not replace the old method. If you do not specify a url parameter in your data holder, SWX will default to the old method of using _parent._url in the allowDomain call in the SWX data SWF. In other words, existing code will work as usual.

The mod_security issue

Folkert discovered that mod_security doesn’t like a URL being passed as one of the arguments to the SWX gateway. The actual error he got was similar to the following:

[Fri May 25 11:44:34 2007] [error]
[client XX.XX.XXX.XX] mod_security: Access denied with code 403. Pattern match "!/imp/login\\.php" at HEADER("Referer") [id "300018"] [rev "3"] [msg "Generic PHP code injection protection via ARGS"] [severity "2"] [hostname "mydomain.com"] [uri "/php/swx.php?url=http%3A%2F%2Fmydomain%2Ecom%2Fswx%2FsweetX%2Eswf&debug=true&service
Class=Twitter&method=publicTimeline&args=%5Bnull%5D"] [unique_id "PyzB4lNikW4AAFdCLVIAAAAE"]

The Generic PHP code injection protection via ARGS rule in the default mod_security rules that was triggered is the following:

#really broad furl_fopen attack sig
#tune this for your system
SecRule REQUEST_URI "!(/tiki-objectpermissions|aardvarkts/install/index|/do_command|banner_click|wp-login|tiki-view_cache|/horde/index|/horde/services/go|/goto|gallery2?/main|ad-?server/adjs)" "chain,id:300018,rev:3,severity:2,msg:'Generic PHP code injection protection via ARGS'"
SecRule REQUEST_URI "\.php(3|4|5)?(\?|&)" chain
SecRule ARGS "(ht|f)tps?:/"

The rule in question is labeled as being “really broad” and there is a note there that it should be tuned to your system. In fact, there are exceptions in the default file for common web applications like WordPress, the Tiki wiki and Horde.

Workarounds

The first workaround, of course, is to alter the mod_security rule, above, to include SWX in the list of exceptions. I haven’t tested this, but adding |swx to the list of exceptions should do this. Unfortunately, not everyone will have access to this on a shared account, which brings me to the second workaround, provided (and successfully used) by Folkert: use .htaccess.

To disable mod_security for all SWX calls, add the following lines to your .htaccess file:

<IfModule mod_security.c>
    <Files swx.php>
        SecFilterInheritance Off
    </Files>
</IfModule>

Update: Another workaround is to disable mod_security completely. Again, in the .htaccess file, you can use:

#Disable mod_security as it doesn't work with Flash file uploads and some SWX APIs
SecFilterEngine Off
SecFilterScanPOST Off
#End disable mod_security

Note that for uploads to work with the Flickr API, you must disable mod_security using the above lines in an .htaccess file placed in the /flickr/upload/ folder of SWX PHP.

Update: Another workaround (thanks again to Folkert) is to add the URL to swx.php in your exclude.conf file and remove just the rule that’s causing the problem, as below:

<LocationMatch "path/to/swx.php">
    SecFilterRemove 300018
</LocationMatch>

A look ahead to cross-domain data exchange in SWX

Cross-domain data exchange is a very important feature in SWX. Among other things, it allows API publishers to create public SWX gateways that can be accessed directly from Flash using SWX. Looking ahead, and in light of this issue with mod_security, I foresee that there will be one more change to cross-domain data exchange and security work in SWX.

Starting with the next beta, there will be a third way to give cross-domain access to the SWX gateway: This time by using a whitelist on the server side.

In the SWX configuration file (swx_config.php), there will be an array of allowed domains that you can edit. Something along the lines of:

$allowedDomains = array ('http://aralbalkan.com', 'http://swxformat.org');

These domains, then, will be written into SWX data SWF files (if the $allowDomain setting is set to true).

Again, this method will not replace the other two methods outlined above but it will provide a third alternative.

The advantage of this method is that you will not need to send a url parameter from the client or allow access to the SWX data SWF. So, it requires the least amount of work from the client. This is the best solution for non-public SWX gateways where you know the exact URLs of the SWF files that will access it.

The disadvantage of this method is that there will be multiple System.security.allowDomain calls in all resulting SWX data SWF files, thereby increasing the size of these files if there are too many domains listed. (So this is not the ideal solution for a public SWX gateway).

In summary

There are currently two ways to allow cross-domain data exchange in SWX and, with the next beta, that number will be three. These are:

  1. Use System.security.allowDomain(dataHolder); on the client to allow the loaded SWX data SWF access to the main SWF and do nothing else. (The SWX data SWF will allow access to itself from the main SWF using System.security.allowDomain(_parent._url))
  2. Do not allow the SWX data SWF access to the main SWF file but pass the url of the current SWF to the SWX gateway by adding it to the data holder (dataHolder.url = _url;). The SWX data SWF will allow access to itself to the url that was passed to the gateway.
  3. Do not allow the SWX data SWF access to the main SWF file or pass a URL from the client but rather add a list of allowed domains to the SWX configuration file on the server.

Cross-domain data exchange is always a hairy topic as it brings with it the Flash sandbox security model. I believe that these three methods will give you the flexibility you need in implementing cross-domain data exchange with SWX without too much difficulty. At the end of the day, we’re lucky that we actually can do cross-domain data exchange, unlike technologies like Ajax that cannot.

Thanks again to Folkert for uncovering the mod_security issue and for providing the workaround.

Cross-domain data exchange in SWX Beta 1 and an issue with mod_security

Leave a Reply