Thanks again, Larry! ![]()
Monthly Archive for May, 2007
Cross-domain data exchange in SWX back-story
In 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 read System.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 reads System.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:
- 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 usingSystem.security.allowDomain(_parent._url)) - 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. - 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.
Read more about this release in this post and on the download page.
The main changes here are that your applications will not need to call System.security.allowDomain() on the loaded SWX SWF data files. Instead, if you are not using the SWX API, you will need to pass a url parameter into your data holder movie clip and set its value to _url. The SWX server, after validating that this is a valid URI, will use it in the allowDomain() statement it places in the SWX data SWF to allow your application to access its data. This is a much better way of doing things than the previous method which used (_parent._url) and meant that your application had to allow the SWX data SWF access to itself also. Although you should never place any sensitive data in a SWF, this approach makes more sense in terms of security.
If you do not set a url parameter in your data holder, SWX will function as it did before and you will need to specifically allow domain the data holder movie clip (i.e., your existing apps should continue to work regardless of whether you use the new method or the old.) The Full API in the Beta release uses the new method.
Also, there is now a cancelAllCalls() method in the Full API that you can use to cancel all outstanding SWX calls in the queue.
In the meanwhile, though, if you have deployed examples that stopped working yesterday, please either add System.security.allowDomain(gatewayUrl); to your examples (if you didn't already have it) or update from svn and use the full API, which will do this for you automatically.
There is one big API change in Beta 1 that will affect all existing SWX applications that are running off the public SWX gateway on swxformat.org (http://swxformat.org/php/swx.php).
The arguments property for your data holder movie clips is now args. This change was made for two reasons: One, arguments is a reserved word and, although it doesn't clash with the built in arguments object (for method calls), I still didn't feel right using it. The second reason is to make it consistent with the new SWX full API in Beta 1. See this post for an example of the full API (note: I just updated that post to reflect this API change so it will be slightly different to how it was yesterday).
I will amend this post with an update once this is done. Please update your applications accordingly once the public gateway is upgraded.
This change (of course) will not affect any local development versions of the SWX gateway you may have until you upgrade to SWX Beta 1.
Update: I'm still updating all the sample apps (of which there are multiple versions to demonstrate usage without the api, with the minimal api and the full api) so this, along with the beta release, is going to be delayed to tomorrow).
Update: I've updated the gateway on swxformat.org to the Beta 1 version. Please implement the API change outlined above in your applications if you are hitting the public gateway here.
At the same time as this release, I will be removing the public SWX gateway on aralbalkan.com. If you are currently using this, please switch to the official public SWX gateway on swxformat.org: http://swxformat.org/php/swx.php.
Finally, if you're using the SWX Twitter API, please note that the method signature for the getNumFriendsUpdates call has changed. The order of the parameters is now friend name first, then (optionally), the number of updates to receive (up to the default, which is 20.) This used to be the other way around but I changed it since the friend name is a required argument and must come first.
Update: Instead of the Alpha 0.3 release as planned, I will be releasing Beta 1 today (May 15th, 2007) this week. See this post for more information.
You can read more about this on my blog.
Read more about this release in this post and on the download page.
