Grab password with XSS

Automatic completion of passwords in web forms allows attackers to grab your password if an XSS vulnerability exists.

We don’t usually associate XSS vulnerabilities with compromised passwords, but it is sometimes possible to steal login credentials through XSS vulnerabilities on a website. Take a look at the example attack below.

Example attack

  1. Find any XSS vulnerability on a domain.
  2. Use the vulnerability to load the login page into an iframe on the vulnerable page.
  3. Wait for credentials to be loaded into the form by the browser or an extension.
  4. Leverage the Same Origin Policy to obtain values from the login form in the iframe.

The example is demonstrated on this page.

Similar approaches have been described before (see some links below this article), but I could not find any solid advice on how to mitigate this type of attack.

Prevent

These are some options developers have to mitigate the attack described above.

  • Don’t allow login-screen when already logged in

Always redirect your login page to a different page when the user is already logged in. That way, the attacker cannot simply include the login page, the login form won’t be displayed, and the browser won’t automatically load the user credentials.

  • Don’t allow framing of login page

EDITAs pointed out by avlidienbrunn in the comments below, X-Frame-Options is not a solid solution to mitigate the attack. It can be circumvented by abusing the Same Origin Policy by initiating a new window instead of using frames. The paragraph below is therefore not accurate.

Similar to the solution above, the developer can set the header X-Frame-Options: Deny so that the login page cannot be included in an iframe by the attacker. See the mitigation in action here (tested to work in Firefox).

It’s worth pointing out that those two mitigations can be circumvented by using Javascript to construct a login form on the fly. The successfulness of this work-around depends on the way the password manager remembers credentials.

Firefox, for example, is vulnerable to this type of work-around. It displays credentials on a domain-name basis, meaning the credentials will also get inserted in a form that isn’t on the login page.

If we look at Chrome, it surprisingly shows that it’s protected against this whole class of attack by not allowing password fields to be accessed whatsoever. The demo above seems to have no effect on Chrome. (Side remark: I have difficulties forcing Chrome to remember credentials, so wasn’t able to test the demo thoroughly.)

My last example is LastPass, which has its very own approach to remembering credentials. It offers url rules to link urls to login credentials but links login details to exactly one page by default. This effectively disables any XSS from grabbing the password on a page that isn’t the login page. Only an XSS vulnerability on the login page could then be used to obtain the secret, drastically reducing the attack surface.

Wrap-up

We saw some examples of how an XSS vulnerability can be used to steal passwords that are remembered by password managers. Through some simple coding, developers can prevent cross-page password stealing through the use of iframes. On the browser side, we notice that Firefox remains vulnerable to attackers that construct a login form on the fly. Just like Chrome, other browsers should disallow Javascript from accessing the value of a password element.

Finally, I’d like to take some time to advocate the use of passwordless logins (I strongly suggest reading it). Passwords are and will always be a weak link in security. They get stolen, through any of so many possible attacks, and users often don’t care to change them or maintain an extensive (safer) set of different passwords. Then why not opt for a type of login that eliminates the need for better password management by reluctant users and undoubtedly keeps them safer in the long run?

Related

Comments

The following comments originally appeared on a different blog and have been copied here for reference.

avlidienbrunn

X-Frame-Options won’t protect against this as you can open a new window and do the same thing. The only real protection against this is to use autocomplete=”off” or emulate the same functionality in browsers that doesn’t support it.

Pieter

@avlidienbrunn, that is true , I didn’t think of the new window cross-domain possibility. However, the autocomplete=”off” is not a solid solution, because it appears to lose support for several modern browsers, if this source is to be trusted: http://stackoverflow.com/a/3868314/436953

avlidienbrunn

Yeah, seems browser devs thought it would be a good idea to remove the feature. However, the same functionality can be achieved by using type=”text” and styling it into a password field with CSS. Another thing you could do is to use a nonce in the password field’s name. That way the browser won’t recognise the input :) Anyway, I just wanted to point that out and also chip in a say that the “open new window method” works in Chrome too. However, it requires a click from the user to get around popup blockers in some scenarios.

Pieter

Thanks for your additions. I like the obfuscated type=”text” trick. Although I have a feeling that password managers like LastPass are able to recognize the login form, regardless of how random/”noncy” the input field’s name attributes are. I may be wrong.

Leave a Reply

Your email address will not be published. Required fields are marked *