Technical Insight-Vulnerabilities-Web Application Security-WhiteHat HackerKast

#HackerKast 29 Bonus Round: Formaction Scriptless Attack

Today on HackerKast, Matt and I discussed something called a Formaction Scriptless Attack. Content Security Policy (CSP) has put a big theoretical dent in cross site scripting. I say theoretical because relatively few sites are taking advantage of it yet; but even if it is implemented to prevent JavaScript from loading on the page, that doesn’t necessarily remove the possibility of attack from HTML injection.

For example, let’s say you have a site that has CSP set up to prevent inline and remote JavaScript from loading using the nonce feature, which requires all script tags to include the nonce before they will load. The nonce is probably based on some locally known secret XOR’d with the user’s credential or something similar. Whatever the case the CSP nonce is not known. But what they really want to do is submit some form. Now the form itself might protect itself in a different way, using a server-generated nonce (a second one) to prevent cross site request forgeries. Barring any side channel attacks, MitM attacks or attacks against the server itself, it seems like this might stop you in your tracks.

HTML5 to the rescue! Let’s say the form has an id set of id=”form1″. HTML5 has a feature where any input field anywhere on the page (yes, even outside of the form block) can say that it belongs to any form using the “form” parameter (e.g. form=”form1”). That might be somewhat bad, because perhaps I can include an extra form field and make the user do something they didn’t mean to do. But worse yet, HTML5 also has a feature called formaction. Formaction allows me to change the location where the form is being submitted.

So if the attacker submits an input field that associates itself with the form that contains the secret nonce and also with the formaction directive which points the form to the attacker’s website, it’s pretty much game over if the user clicks on that button. So now the trick is to get the attacker to click on the button. Oh, if only there was a way to get people to click on arbitrary places on a page from another domain… oh wait! Clickjacking!

So if the site is using CSP but not using X-Frame-Options or similar techniques to prevent the site from being framed, the attacker can frame the page and force the user to click on the evil button that has set a formaction which points the form back to the attacker’s site. The attacker then takes that nonce, creates a page that automatically uses the nonces and forces a CSRF request with the secret nonce. So much for CSRF protection! Here is the original vulnerable page and here is the clickjacked version of it with semi-opacity enabled to make it easier to see (tested in Firefox only).

Scriptless attacks aren’t new, Mario Heiderich for example has been working on them for years, but they are deadly. It’s not quite the same thing as a cross domain read in this case, but it has the same effect – allowing the attacker to read information from the target domain for use in an attack. I highly recommend using X-Frame-Options on all your pages. But that only stops one form of the attack. It’s still possible to social engineer people and so on. Why devs need to associate input fields with forms outside of the form block is still a bit of a mystery to me and why they need to change the form action after the fact — even overriding the original location — is also a puzzle. But with every new feature comes a new way to abuse it. HTML5 is an interesting beast, that’s for sure!

Update: As mentioned on Twitter, you can use CSP to block formaction, but you have to do that or the attack will still work with other CSP rules. Also you can do the equivalent of X-Frame-Options in CSP as well. So a properly configured CSP might actually save you – very cool!

Tags: Cross Site Scripting, csrf