(new) Adobe Flash Player security hole found, flXHR’s response
The devil is in the details
Unfortunately, this post is here for one reason – to discuss a ‘hole’ that I recently discovered which is not at all evident from (and moreover, contradicts in small part) Adobe’s own official documentation on the security model.
In a nutshell, the hole comes from the fact that Adobe *only* uses the domain that the SWF file itself comes from to make the server policy checks. The domain of the URL of the hosting HTML page is *not* considered, even though the SWF’s executable code (similar to any remotely loaded Javascript files) will in reality execute in the context of that page. So, the divergence between the security sandbox of remotely loaded Javascript (the page domain) and remotely loaded flash assets (the SWF domain) presents a rather clumsy hole that authors may very well fall into, as I did.
The Flash Player has an “auto-trust” implicit to any SWF regarding communication back to the domain from whence it came. Moreover, when a SWF comes from a particular domain, no matter where in the directory structure it comes from, the SWF is granted automatic and unconditional permission to communicate in any way, shape, or form it pleases with any (public) part of the originating domain’s server, regardless of any server policies the server may have.
So, imagine that you have SWF which has code logic to make calls back to server(s) in it. Merely hosting that SWF in a publicly accessible way means that the SWF will be able to talk to any part of your server’s public access area, regardless of where that SWF is linked to and running. And regardless of if you want to restrict that SWF’s communication to your server with server policies, either partially or entirely, you will not be able to. Basically, you can publish a policy that controls SWF’s from everywhere else in the world, but you have no policy control over your own SWF’s.
In some RIA situations, some SWF files have to be more permissive/flexible in their functionality, allowing Javascript to tell it some or all of the parameters it uses to decide how to communicate with which server. In the current model, they become a liability to any hosting service, because that hosting service cannot control how that SWF will behave when it is “calling home”.
On the surface, you may say, ‘well, if I host the SWF, I have control over what the SWF can do by virtue of the fact that I can decide not to host a SWF that has “rogue code” in it.’ But there are many scenarios in which content providers may want to provide “clients” (ie, flash RIA widgets), such as chat interfaces, email, FTP, etc, and they may by necessity need to host those widgets on their domain, but not want “prying eyes” to abuse those widgets to get at information (or push unwanted information) at the same server hosting the widget SWF file itself.
They may want to host the SWF file for a chat service on their HTTP server, but want it to only be able to communicate with a specific chat service server. Or, they may want to allow their SWF to run only inside of pages they control (by virtue of the HTML/Javascript they publish), but if the SWF is itself publicly available (and it must be to be on a public website), any malicious person can pull in that SWF, interact with it on that malicious domain, but get a “free ticket” to communicate back to the originating server.
To make matters worse, Adobe’s own whitepaper on Flash security says (on page 29) that a server can unconditionally publish an “empty” policy, which by default should deny *all* access by SWF’s (regardless of origination domain). This policy is mentioned specifically for a scenario where a web server expects to host SWF’s that can cross-communicate, but it does not want any of them to communicate with the hosting server itself. However, the ‘auto-trust’ overrides this empty policy, and therefore authors cannot deny access to SWF communication if they host the SWF, no matter what they do.
In this day and age, where SWF’s are powerful RIA’s that get integrated with javascript into public pages, a SWF should not be considered an “island” that runs with its own set of rules (ie, only inside its originating domain). Yes, it’s far less easy to arbitrarily and dynamically hack the operation of a running SWF as opposed to running Javascript code, but nevertheless, SWF’s by nature often have to open their doors to make integration possible, and when they do, if the server policy isn’t *fully* enforced, problems are likely to ensue.
The crux of the matter is that *both* the domain that a SWF comes from, and the domain that it executes in, are important domains to consider when checking server-side opt-in policies. Without the page-domain checking, the server model is limp in this area, and susceptible to malice or ignorance to a far greater extent than most realize (including myself, as an avid defender of Adobe’s model, until recently!)
You definitely raised an interesting point regarding Flash security. I wouldn’t call this a security hole though, but rather a missing security feature.
It’s always up to developer to develop secure application according to the platform capabilities and limitation. A “good” developer can break the toughest security model in a sec
Comment by guya — August 28, 2008 @ 10:47 am
@guya- I think the reason I chose to use “hole” instead of “gap” or “missing feature” is because of point #2 in the page-1 summary — that the behavior is contrary to Adobe’s own security white paper (bottom of page 28) on the topic.
But yes, I agree wholeheartedly that developers/authors need to be more diligent. That’s why I spent an entire month writing and testing (some fairly complex) code to “plug” the hole in the flXHR project so that flXHR can’t be abused (purposely or inadvertently).
But, clearly, my code is not nearly as efficient as if Adobe would address the hole/feature with their native code. And my code doesn’t do much to help all the other flash .swf assets out there which may be vulnerable to such a thing (although the code I wrote *is* in its own class so it *could* be adapted to other projects somewhat straightforwardly).
I guess that’s mostly what I am hoping will come of all this, so that eventually my code won’t be necessary, and other flash content developers won’t have to worry (as much) about this kind of feature-gap.
Comment by Shade — August 28, 2008 @ 12:56 pm
The problem is your underlying assumption is incorrect. You said:
“The domain of the URL of the hosting HTML page is *not* considered, even though the SWF’s executable code (similar to any remotely loaded Javascript files) will in reality execute in the context of that page.”
However, SWF is executed in the context of the SWF’s origin, not of the surrounding page and does not have access to the surrounding page (unless both SWF and HTML are from the same origin OR you enable cross-domain scripting explicitly with allowScriptAccess=always). So it is not the same as importing JavaScript via the SCRIPT tag.
Comment by LDA — October 9, 2008 @ 3:29 pm
I understand that the SWF logically operates in the originating domain security context. And I understand how SWF differs from JS, in that SWF provides this special ability to self-contain its execution to a remote security context (*unless* that barrier is intentionally taken down by the author).
But physically, the SWF is operating inside of an HTML page on perhaps a different domain, and moreover, may be interacting with the javascript of that page on the different domain (if the author allowed it).
In my opinion, what matters most here is the practical security context, which for flash on a webpage, can look a lot more like a mix between the page’s domain and the SWF domain, than *just* the SWF domain.
I know there are access controls (‘allowscriptaccess’ and ‘allowdomain’) which are generally in place to help prevent (or allow) the swf from stepping out of its security context bounds when on a page from a different domain. However, there are plenty of times when a flash file (like flXHR for instance) must be granted permission to talk with the surrounding page regardless of the domain, to accomplish its tasks or goals.
A stand-alone, totally security-sandboxed flash is fine for say a flash ad, but real interactive RIA type flash often needs to step outside it’s walls from time-to-time, and so authors must sometimes breach this defense.
So, if you have such a flash file, which, internally published *and* through the HTML it’s hosted in, has granted this cross-domain access, then practically speaking, that SWF is now operating in a hybrid security context, a mixture of both the page domain and the originating domain.
It is *this* use case which leads me to assert that both the page domain and the swf-domain would be proper to check in resolving cross-domain policies from a server.
Think about it this way… if Adobe’s flash *did* do as I suggest, in most cases (where the page-domain and swf-domain are the same), the behavior wouldn’t be any different than it is right now. But in the set of cases where a SWF is operating in the hybrid context, the cross-domain policies *would be* more secure than they are now, assuming that only the swf-domain need be considered.
I’m simply suggesting that giving developers the ability to breach the strict originating domain security context (ie, the “AllowDomain” actionscript call) but not having the policy file model also support this hybrid context is where the “hole” comes from. And try as I may, the implementation I put in place to protect flXHR from being exploited while in the hybrid zone is limited in its effectiveness — only a native solution from Adobe would fully plug this hole.
Comment by Shade — October 9, 2008 @ 4:52 pm
[...] was the class added to flXHR.swf in a previous alpha release to address the needs discussed in this blog on security model holes. However, it was discovered through further testing that IP addresses, single-word domains (like [...]
Pingback by Changes and new features in flensed 1.0 | the Fresh! — December 5, 2008 @ 7:32 pm