Friday, April 4th, 2008
Taking ownership of someone else’s content is always a tricky deal. Nate McFeters and I spoke about some of the issues related to taking “ownership” of someone else’s content last year at Defcon, but we continue to see more and more places willingly accepting third party content and happily serving it from their domain. I came across an interesting cross domain issue based on content ownership that involved Google. Google has fixed the issue, but I thought the issue was interesting so I’ll share the details… but before I do… I wanted to mention the efforts put forth by the Google Security Team (GST). Fixing this issue was not trivial… it involved significant changes as to how content was served from Google servers. Needless to say, the GST moved quickly and the issue was fixed in an amazingly expedient and effective manner… KUDOS to the GST!
On to the issue:
I discovered that users could upload arbitrary files to the code.google.com domain by attaching a file to the “issues” portion of a project. The uploaded file is then served from the code.google.com domain. Normally, these types of attacks would make use of the Flash cross domain policy file and the System.security.loadPolicyFile() API, however due to the unique path of each project, the cross domain capabilities of Flash are very limited in this instance as policy files loaded via loadPolicyFile() are “limited to locations at or below its own level in the server’s hierarchy”.
Flash isn’t the only option here though. Java has a different security policy and uploading a Java class file to the code.google.com domain gives me access to the entire domain, as opposed to only certain folders and sub folders.
Sounds pretty straight forward huh? Well, I ran into some issues as the JVM encodes certain characters in its requests for class files made via the CODE attribute within APPLET tags. After poking around a bit, I realized that requests made via the ARCHIVE would be sent as is, without the encoding of special characters. With this newfound knowledge in hand, I created a JAR file with my class file within it and uploaded it to code.google.com.
Now, the CODE attribute is a required attribute within the APPLET tag, so I specified name of the class file I placed within the JAR file. When the APPLET tag is rendered, the JVM first downloads the JAR file specified in the ARCHIVE attribute, the JVM then makes the request for the class file specified in the CODE attribute. In this instance, the request for the class file specified in the CODE attribute will fail as the class file is not on the code.google.com server (even if it was, we wouldn’t be able to reach it as requests made via the CODE attribute are encoded). The failure to locate the class file causes the JVM to begin searching alternate locations for the requested class file and the JVM will eventually load a class file with the same name located inside of the JAR file…
Once the class file is loaded, the JVM will fire the init() method and Java’s Same Origin policy allows me to use the applet to communicate with the domain that served the applet class file (as opposed to the domain that hosts the HTML calling the APPLET tag). Here’s a screenshot of the PoC page I was hosting on XS-Sniper.com.
I don’t think there is a tool on the market today that even attempts to detect something like this and I’ve met many “security professionals” that have no idea that vulnerabilities like this even exist. This isn’t the first time I’ve come across a cross domain hole based on content ownership. I’m expecting we’ll see a lot more of these types of vulnerabilities in the future as cross domain capabilities becomes more prevalent in client side technologies and as content providers become more and more comfortable in taking ownership of others content.