Sunday, December 30, 2012

Weaponizing Pt 3: CodePen Redux

Note: CodePen has been notified of these problems and has fixed them. This is an analysis of how their original fix was bypassed and these techniques could possibly be applied to future redirection vulnerabilities.

Since my post about using code playgrounds as attack platforms, CodePen has added some JavaScript that will alert a user if the pen is trying to redirect them to a 3rd party domain. If you use the example redirect code from earlier in this series, you'll be presented with a prompt asking you if you'd like to leave CodePen. This article explains how to work around this code and carry out a redirection.

At the time of this writing, you can use Chrome developer tools or FireBug to see this code in action:
window.__canLeave = false;

window.onbeforeunload = function() {
    if (!__canLeave) {
        return "WARNING! You are leaving the safety of CodePen! Are you sure you want to leave?";
    }
};

setTimeout(function() {
    window.__canLeave = true;
}, 200);
In this code, they are hooking the onbeforeunload window event, which will execute their function when the browser window attempts to "unload" (read: navigate away from) the current page. If you tried our form-based redirect, you may have noticed that they will also attempt to overwrite form actions pointing to other domains.

Bypassing the Prompt
There are a couple of ways we can disable this prompting function. The first, blunt approach, is simply overwriting the window.onbeforeunload hook. We'll replace their function with a blank one of our own, then carry out our redirect.
<script>
window.onbeforeunload = function() {null;}
var target = 'win dow.loca tion="htt p://www.goo gle.com";';
eval(target.replace(/ /gi, ''));
</script>
A slightly more elegant approach is to not modify their function logic, but simply meet the function's requirements for a redirect. Because their __canLeave variable is attached to the window object, we can access it from our closure. So, let's just overwrite it:
<script>
window.__canLeave = true;
var target = 'win dow.loca tion="htt p://www.goo gle.com";';
eval(target.replace(/ /gi, ''));
</script>
Bypassing the Action Rewrite
This one is pretty easy. They're looking for form actions in our HTML, so we can overcome their form action filtering by dynamically assigning our form's action in JavaScript. Chaining our two techniques together gives us the following working redirect code:
<form id="bbb" />
<script>
window.__canLeave = true;
document.getElementById("bbb").action = "http://www.google.com";
document.getElementById("bbb").submit();
</script>
So Long And Thanks For All The Phish
So, besides open redirects, what else can we do with all of this? Well, CodePen has started rolling out professional accounts, and you no longer need Github to make one. Why not use their site to make a pen and go phishing?

Using data URIs combined with redirects, it would be easy to clone their login page in a pen. Add a message saying, "This pen is protected. Please log in to continue." We can now redirect any entered credentials to our own 3rd party site, log them for future use, then bounce the user to a real pen.

Summary
Although the examples in this series were trivial, they could easily be leveraged as a malicious attack platform. As CodePen begins to roll out more of their own features, especially those that people pay for, these techniques will become more exploitable.

Return to Part 1: Overview or Part 2: jsFiddle.

Thursday, December 13, 2012

Weaponizing Pt 2: Framebusting jsFiddle

In part 1 of this series, we looked at how we could use code playgrounds as open redirect services. One of our targets was jsFiddle. jsFiddle attempted to avoid some of our redirection problems by sandboxing a user's code in an iframe. On the surface, this seemed to solve the problem: by constantly leaving a JSFiddle banner on the page, the user is always reminded that they're viewing a fiddle.

At this point, the attacker needs to escape their horrible sandbox prison. Incidentally, this has been done before: framebusting to the rescue. Framebusting is traditionally a technique used to prevent UI redressing, essentially allowing a victim page to bust out of a potentially malicious iframe. We can use this technique to defeat jsFiddle's sandboxing iframe.

Again, we'll add our redirection code to the HTML area of our fiddle:
<form id="fun" action="http://www.gawker.com" />
<script>document.getElementById("fun").submit();</script>
If you run this fiddle now, you'll see the Gawker homepage, along with a jsFiddle banner along the top of the page. Now we can use JavaScript to escape the shackles of our imprisonment, improving our redirect. By changing our code to the following, we can bust out of our iframe and redirect properly:
<script>if( self != top ) {top.location = self.location;}</script>
<form id="fun" action="http://www.gawker.com" />
<script>document.getElementById("fun").submit();</script>
This extra line checks if our current script's location is the same as our parent window's location. Because our script is running in a frame, our location (in the frame) is different than the parent's location (out of the frame). Whenever this happens, we set the parent's location to our current location. Our script then continues to our redirect as normal.

Summary
This again reiterates how difficult it is to control client-side functionality in a language as robust as JavaScript. When JavaScript controls the DOM, and the DOM can have embedded JavaScript, it only takes one oversight to take full control of content.