Adobe Responds... Sort Of

Cross-posted from Skeptikal.org


Adobe has published a response to the latest issues I've been talking about. Somehow, they have managed to neatly dodge the issues in question and fixate on the Same Origin Policy. Is that policy news to anybody? Of course not. That's not the point. That's not even the issue, though I do believe the policy is flawed, which I'll explain in a few paragraphs.

Adobe continues to compare this to uploading Javascript files. Here's the difference:

If I upload a .js file to a webserver, I cannot execute it in the context of that server. Javascript alone will not execute.

If I upload a .html file to a webserver, I can execute Javascript within it in the context of that server, because my browser recognizes the text/html content-type header that the webserver sends.

If I upload a .html file to a webserver, but an application/zip header is sent by the server, it will not render at all.

If I upload an HTML file with a non-html extension to a webserver, and the server does not send a text/html content-type when serving the file, I cannot render HTML or execute Javascript.

If I upload a ZIP file with HTML prepended to it, I cannot render HTML or execute Javascript.

If I upload a .swf file to a webserver, I can execute it in the context of that server.

If I upload a SWF file with a non-SWF extension to a web server, I can execute it in the context of the server.

If I upload a ZIP file with a SWF file prepended to it, and the server sends an "application/zip" content-type, I can execute it in the context of the server.

Flash's handling of potential code is clearly MUCH more permissive than Javascript's.

This makes it far easier to upload an object to a webserver- a Flash file can look like anything to the server and still be executable, as long as it starts with the right sequence of bytes. In many cases, simply changing the file's extension is enough to bypass upload restrictions. In other cases, you have to get crazy with it, but as noted in the original post, the entire ZIP family of files can have a SWF embedded in them while still being valid. Checking whether the file is a valid ZIP file will do you no good. The only way to be sure that the file does not contain a SWF is to specifically look for a SWF header. Any security professional will tell you that a technology that requires a blacklist approach to input validation is poorly designed.

There are some solutions for the security administrator. They aren't easy to implement. The best thing to do is place all your user-generated content on a separate server. For large web applications, this is probably already happening. But do you think that every prebuilt forum, ecommerce, blog, and gallery application out there is going to get redesigned to fix Flash's problem? Do you think the hobbyists and mom-and-pop shops are going to set up a separate server for holding this content? As most of them don't even have one dedicated server, this is not just unrealistic to expect, it's virtually impossible. Again, I'll pull out the example of bugs.adobe.com, a prebuilt issue tracking application that stores files on... bugs.adobe.com. I reported this issue several days ago, and not only have they not moved all user-generated content off the server, they haven't even disabled the file upload feature.

The other solution for administrators is to serve user-generated files with the content-disposition: attachment header. This is relatively easy to do, and it's the only reasonable thing they've suggested. It is still hardly an ideal solution though. First off, some user-uploaded content shouldn't be served with this header. Images that people expect to be able to inline in other web pages are one example. Validating images is obviously easier (and more common) than validating zip files, but the point stands.

Now, let me be clear: The Same Origin Policy is a completely separate issue from the execution of the content, but since Adobe won't stop talking about Flash's Same Origin Policy, allow me to demonstrate exactly why it is designed wrong.

If a Javascript file hosted on foo.com is included in a web page on bar.com, that file can only affect the bar.com domain. Same origin policy. Woot.

If an HTML file hosted on foo.com is iframed into a web page on bar.com, that file can only affect the foo.com domain. Same origin policy. Woot.

If a Flash file hosted on foo.com is embedded in a web page on bar.com, that file can run Actionscript on foo.com, as well as execute Javascript on bar.com.

All the attention to this point has been on uploading malicious files, but let's take a look from another angle. What if victim.com has its own Flash objects, which use Javascript calls to interact with the web pages they're included on? This is not an unreasonable assumption- it's the very reason that a Javascript interface is built into Flash player. Here's the problem: these Flash objects can be embedded in evil.com's webpage. evil.com can run his own Javascript which modifies function prototypes (again, only in the context of evil.com), poisoning the functionality that victim.com's Flash object relies on. When that Flash object then uses data from the Javascript side of things to communicate with its origin server, you again have cross-origin interaction.

What kind of Same Origin Policy allows code to execute on multiple origins? A seriously flawed one.

From Adobe's response: "[The Same Origin Policy] states that two pieces of content hosted on the same domain and loaded by the same protocol trust each other. Conversely, two pieces of content hosted on different domains do not trust each other and cannot interact." If this was the way it worked, we would have no problem. In my examples, I used 2 pieces of content (a SWF and an HTML page with Javascript), on two domains (foo.com and bar.com), using the same protocol (HTTP), and I made them trust each other. By their own definition, Flash's policy does not work. Adobe's response is dead wrong.

--Mike Bailey