Skeptikal.org

Saturday, November 14, 2009

Adobe Responds... Sort Of

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.

Labels: ,

Friday, November 13, 2009

Flash Origin Attack FAQ

Okay, people are looking at this Flash issue. Neat. A lot of people don't fully understand it, which may be my fault. Here, I'm going to try to respond to some of the questions and comments that I've received from various parties.

This is not a single issue

While it is a single, basic issue that enables this exploit, it is the
intersection of that and several others that makes it critically bad.

Specifically, the fact that an uploaded file can attack a server is hardly news. As mentioned in my original post, Adobe has acknowledged this issue with advisories multiple times. If you were already aware of it, good on you. However, it still is new to most website administrators, and more importantly, these are the people that Adobe expects to fix it.

The part that is new, is the focus of this research, and admittedly could have been described better, is that the Flash player will execute any file it is asked to execute. The HTML <embed> tag is used to include objects that the browser may not be natively able to handle. Arguably, this may be a browser issue as well, as the content-type supplied by HTTP headers should take precedence over the type attribute specified in the HTML page, but the plugin itself should also verify that the proper content-type is sent in the server's response HTTP headers before executing the plugin. Flash's plugin does not do so.

If Flash's plugin did handle this correctly, the other issue documented here- that of overloading various filetypes, primarily ZIP, would be nearly useless. The point of that work was to demonstrate just how difficult it is for administrators to filter uploaded content by file validation, and to provide various examples of how to bypass such validation with 100% legal files, which are still potentially malicious. More on that in a moment.

This is not a cross-site scripting attack

The end result of the attack can indeed be XSS, as Actionscript may execute Javascript through the "ExternalInterface" method, but the source of this problem is not necessarily input sanitization. It is a core design flaw in Flash's same-origin policy, combined with the weak content ownership management that is already common on the majority of websites and prebuilt web applications on the internet.

Calling this attack XSS, when it involves no Javascript (arguably, not really a requirement), is not cross-site (again, not really a requirement, despite being in the name), and involves no HTML injection, is a stretch, but the similarity is certainly there, bringing me to the next point:

This attack abuses the user to attack the server

This is where it is very similar to XSS. The whole point is to hijack the user's browser and have the ability to issue requests to, and read the results from the server. In the context of a user's session, this can be a very bad thing. Neither the server itself nor the client's computer is being compromised directly; The web application, and any data or functionality within, is now accessible to the attacker.

Adobe does not intend to fix it

As they have made abundantly clear, Adobe considers this to be the web administrators' problem. Regardless of whether you agree with them or not on this, it is hard to dispute that Adobe's expectation of administrators to prevent this issue is unrealistic.

In fact, Adobe does not appear to be able to manage this issue on their own web properties. For example, photoshop.com is an interactive image library application. Uploaded images are not validated fully, and are stored on (and executable from) api.photoshop.com. This is indeed a separate domain from the rest of the application, and should be safe (though I'd point you to my paper on cross-subdomain attacks and say it is still poor practice), but www.photoshop.com's crossdomain.xml policy specifically allows access from *.photoshop.com.

Next, take a look at bugs.adobe.com. This third-party issue tracking system allows users to upload screenshots (or zip files of screenshots) of bugs. These files are hosted on bugs.adobe.com, and can be used to exploit not only bugs.adobe.com, but again through crossdomain policies, www.adobe.com, www.acrobat.com, www.photoshop.com, and other Adobe web properties.

You'll never guess where www.photographersdirectory.adobe.com keeps its uploaded images. Or where forums.adobe.com keeps users' uploaded avatars.

Clearly, expecting website administrators to understand, not to mention be able to fix this issue is ridiculous and unrealistic. I originally compared this to the GIFAR exploit, which uses very similar attack techniques against the Java plugin. Unlike Adobe, Sun took responsibility and fixed their plugin. Whether they are wrong or right, Adobe is uniquely in a position to create a client-side fix for the Flash users. Until they do so, many websites will remain vulnerable.

Labels: , , ,

Thursday, November 12, 2009

When Flash Attacks...

Adobe doesn't have a great reputation in the security community, given the long string of exploits and 0-days that have come out over the past few years. Most of the research that I've seen, however, has been attacking the Flash player directly, rather than using it to attack web applications. This is akin to looking for buffer overflows in a Javascript parser, but completely disregarding cross-site scripting as an attack strategy.

The attackers, on the other hand, aren't so picky. From the LiveJournal worm that came out a few weeks ago, as well as some other things-I-can't-talk-about, it's clear that they are beginning to play with the interaction of Flash and web applications.

So, I've been researching this stuff as well. I've found a lot of interesting things, all of which will get released eventually. The first piece, on how to abuse a quirk in Flash's origin policy (complete with a ridiculous multistage Gmail exploit), just went live on Foreground Security's website.

Eventually, there will be a whitepaper, a talk, and some tools released. Stay tuned.

Labels: ,

Friday, September 25, 2009

Inside the LiveJournal Worm

On Wednesday morning, LiveJournal was hit by a Flash worm. It was brought to my attention by Dan Goodin over at the Register, and I discussed it briefly with him as he wrote an article about it. Because I've been looking at Flash in depth lately (more on that coming soon), I decided to take a deeper look at the attack. I was able to track down the HTML side of the malware, but couldn't find a copy of the malicious SWF. An email to the LiveJournal staff fixed that, and they were kind enough to also include their own analysis of the attack. Their earlier post generally covers it, but I'll go into a bit more detail here.

It's really a fairly simple worm. As noted by the LiveJournal staff, the payload did much less than it could have.

The real source of the vulnerability was an overly permissive crossdomain.xml file on www.livejournal.com. This is a well-known, but surprisingly common issue- Jeremiah Grossman came up with some basic statistics for this issue in May of 2008- Some 18% of websites (from a very limited, but high-value set of sites) have crossdomain policies that I would consider "permissive." Coincidentally, I have more research on that coming up soon, but for the moment, I'll just say that only a year and a half later, the numbers are considerably worse.

At any rate, LiveJournal's crossdomain policy allowed Flash objects from their lj-toys.com sandbox domain more access than it should have, and allowed this worm to perform requests across domains. From there, it is pretty simple- embed malicious objects in a post, and have those objects make requests to www.livejournal.com, propogating to the profile of any user that views them. The exact steps that the worm takes are as follows:

  1. Perform a blind request to bit.ly (more on this in a moment)
  2. Check whether a user is logged in by requesting and parsing http://www.livejournal.com/manage/profile/
  3. Extract username and email address from that page
  4. Extract last post ID from http://www.livejournal.com/editjournal.bml
  5. Request the contents of that last post
  6. Check whether the post is already infected
  7. Perform another blind request to bit.ly
  8. Infect the post, appending the SWF payload to the body
  9. Perform requests to one of three outside servers (chosen at random), submitting the following as GET variables: username, email address, and the data from the last post

The requests to bit.ly are interesting. Each time the malware is run, it sends a request to bit.ly. Just before infecting another account, it sends a request to another bit.ly link. The results of these requests are discarded, so I believe that they are only made to provide tracking data for the malware author via bit.ly's "info" page for each link. Based on the information from those pages, I estimate that the payloads were executed 9,700 times, and around 3,300 accounts were infected (accounting for a handful of "false clicks" from myself, the malware author, and others). The data on the bit.ly page doesn't provide enough granularity to generate a useful profile of the attack's timing, so I've contacted bit.ly staff to see what further information can be provided. While they are being helpful, I'm not sure I'll be able to get much useful data (I sure wouldn't give it to me).

What lessons can we learn from this? For a user, Flash can be dangerous. It should be disabled by default. Is this news? No. But this is a very clear sign that the attackers know it as well, and it is being exploited. We, on the good guys' side, should be paying attention. For the administrators of a website, there are a few lessons. First, the crossdomain.xml policy is a major failure point, and many sites are vulnerable. Know when you are allowing access. Second, embeddable content can be dangerous. While LiveJournal's system for embedding content is actually quite good, there are really too many things that can be done with active content like Flash to allow it without seriously considering the consequences.

On the plus side, a few things were really done right. Within minutes of receiving reports of strange account activity, LiveJournal staff determined that active content was the culprit and disabled it throughout the site. A crude whitelist of trusted sources (such as YouTube) were enabled soon thereafter, and within a few hours, the faulty crossdomain.xml file was found and fixed.

That fast of a reaction is really impressive, and the corrective measures were pretty much spot on. What's more, LiveJournal decided to be transparent about the whole issue, releasing informative alerts to their users and working with them to fix compromised accounts. Tupshin Harper, director of Engineering and Operations, was particularly helpful to me in analyzing the attack and providing useful data. My hat is off to them- if more people reacted to breaches this way, the web security community would be in a lot better position to deal with attacks.

A few questions are still left unanswered- primarily about the attacker and his motives. The data that was logged by the malware really wasn't particularly sensitive- an email address and a username, basically. I suppose it could be useful for future phishing and spamming attacks, but given the wealth of other presumably-useful information available in a LiveJournal profile, I'm not sure that this was the goal. The code in the SWF isn't particularly refined, so I think that "Proof of Concept" is the most likely explanation. It's also worth noting that the SWF's code is in English, and while psychological profiling isn't really my strong suit, I get the impression this was intended to be neither subtle nor malicious. The servers that received user data to were all cPanel mass-hosting servers, running vulnerable instances of phpBB, Joomla, and other commonly-attacked software. One of the servers is located in Washington, one in Hungary, and one in the Ukraine. I've requested information from those hosting companies, but don't really expect a response. It is also interesting that the "logging" scripts do not actually exist on any of those servers (nor could they, being ASP scripts and the servers running PHP), but the data is sent as GET variables. If the attacker intended to retrieve that data, he would need to compromise either the FTP account or the cPanel account in question to get it from the access logs- a reasonable assumption, but not (by me at least) a provable one.

I'll leave it as an exercise to LiveJournal, bit.ly, and the hosting companies involved to locate the "patient zero" LiveJournal account and, presumably, the attacker. I have no doubt that the data required to locate him is there, but getting it all into one place will probably prove tricky.

Labels: , , ,