Thursday, November 29, 2012

XSS + "Save your password" = pwned

(on HNews)
Basically, browsers often suggest you to save your password and prefill it automatically.

The bug I just discovered: This value can be retrieved from JS side easily(and this means XSS can steal it). Your REAL password. It's not fucking yet-another-CSRF or SQL injection(server side is pwned) or other trivial. YOU are pwned.  Kind of a serious issue.

Very similar to old issue with 'highlighted' visited links, when attacker could know did you visit certain link or not.

Also, XSS can be on any page and user can be signed in or signed out. It will just open iframe or window and get values because of same origin.

DEMO

Browsers should deny access to prefilled passwords from JS.(UPD: not helpful)

P.S. I'm alive and in Asia(now Kuala Lumpur). Don't worry, new stuff will be published soon ;)

I WAS WRONG. (About these two things)

1. Proposed solution will break the AJAX-based authentications since JS will not have access to password anymore. For example you might want to send password in a header:
Authentication: username:password
and to do so you have to use XHR. If you cannot retrieve password from autofilled input authentication will get broken.

2. There is one more workaround - XSS can change 'action' field to 3rd party website and then .submit(). JS doesn't need access to .value - browser itself will send it to attacker's server. Should we restrict sending passwords only to actions on the current page domain(same origin)? Sounds ugly.

Possible solutions:
1. restricting 'action' value to same origin. Ugly?
2. using Autocomplete only when user is interacting with the website e.g. by typing the first letters of the nickname.
3. Ask in the top bar notification "Should we use autocomplete on example.com?" or smth like this. Looks not bad to me.

4. BEST ONE: do not use any autofill. At least for passwords.
Because security of autofills is fucked. The more websites you use - the more probability to be XSSed on the one of them.

37 comments:

  1. this is no bug.

    why do you even wait till saving the password on the browser to retrieve it via JS ? you could do it in real time or on form submit.

    the only serice that would be able to get the password is the service itself that has this form.
    Why would it be different from giving then your password, that they store on their database ?

    ReplyDelete
  2. This problem is known for years...

    ReplyDelete
  3. how is that different of getting the password when a user typed it and before you submit the form?

    ReplyDelete
  4. Bravo. Now show me how you steal my Amazon.com password with your js. You can't. And if I type my password in there your script will have it anyway, even if I don't save it.

    ReplyDelete
  5. Hi,

    A (little) protection against that is the fact the saved password is filled only when the DOM is fully loaded (at least on all the browsers i've try this trick on)... But it's easy to bypass as you only have to setup your XSS to be fired only at the right event...

    ReplyDelete
  6. @codeandcolors you didn't understand it. ask someone to explain - i have no time to repeat.

    Anonymous so what?

    Anonymous you didn't understand it too..

    Anonymous read the title. "XSS". if you find it ou get pass

    @paul ah it's not protection at all :) and bypassed easily

    ReplyDelete
  7. if you already allow XSS vectors, that is going to be the least of your concerns.

    ReplyDelete
  8. This comment has been removed by the author.

    ReplyDelete
  9. The point is that separating account control from code execution is the current trend. Taking control over the account has more impact than XSS in its context, and password suggestion feature builds a way "XSS => lost account" again.

    Imagine an XSS payload logs you out from facebook, then picks up your password from the login form — and all of this instantly and automatically, no need to type anything.

    Wanna demo?

    ReplyDelete
  10. Try to search for related work first: http://jeremiahgrossman.blogspot.ru/2010/08/breaking-browsers-hacking-auto-complete.html

    ReplyDelete
  11. Tie password saving to the endpoint as well as to the form - only fill in the *actual* data when the data is being sent to both the original endpoint and from that domain.

    I suppose if you keep your login pages on a separate subdomain and make sure that browser will only autofill on that subdomain and you accept no user-submitted content for display on that subdomain you could probably keep yourself somewhat safer too. Using an iframe to do authentication would be a bit of a pain though...

    ReplyDelete
  12. @lukegb. good idea. but no flexability at all. I imagine how developers will hate this solution because it's tricky

    ReplyDelete
  13. No, he doesn't. Don't start insulting people if you have no clue about how a system works.

    Go learn something, .
    http://arstechnica.com/security/2012/08/passwords-under-assault/

    ReplyDelete
  14. I don't have your password because i'm an attacker. YOu clearly have no clue.

    >http://arstechnica.com/security/2012/08/passwords-under-assault/
    this link a bit unrelated, it's about server side and hashing. In our case attacker obtains plain password, not hash. Much more dangerous than getting bunch of hashes

    ReplyDelete
  15. Do any server-side mitigation approaches (e.g. setting autofill=false on the field) work to stop this?

    ReplyDelete
    Replies
    1. if autofill=false will stop autofilling the inputs - then yes. but i am not sure if Keepass and others follow the rule

      Delete
  16. Egor again opens America, thanks CO

    ReplyDelete
    Replies
    1. there is nothing *new*, I agree, but subject deserves discussion.

      Delete
    2. Одному мне кажется, что двое русских пытаются общаться на английском?

      Delete
  17. If you make a hidden form with js, will the browser autofill it?

    What browsers are vulnerable? Is it chrome only?

    ReplyDelete
    Replies
    1. 1) don't know.. doesn't matter since you can iframe and extract values from proper URL
      2) don't know, I checked with chrome but all browsers are supposed to work in the same way. because JS needs access to values thus values are plain text passwords..

      Delete
    2. 1) Только что та же идея пришла в голову :)

      А что это за менеджер паролей такой? Встроеный в хром? Файрфоксовый так же работает? Там надо подверждать автозаполнение, или оно автоматом работает?

      Delete
    3. Сейчас проверил на mail.ru (javascript:alert(mailbox__password.value)) - почему-то не работает.

      Delete
    4. 1) Во фрейме ты будешь тоже залогиненым, а в своей форме - нет.

      Коммент выше - проверял в фейлфоксе 3.

      Delete
    5. ПыСы. А есть на русском, кроме хомякабра? У меня туда инвайта нет, да и общий уровень в it безопасности там на уровне плинтуса.

      Delete
    6. Даже без автофилла паролей можно стырить логин у незалогиенеого пользователя.

      Delete
    7. зачем писать на плебейском русском? тут только на английском

      Delete
    8. Ну на хомякабре ты же пишешь? Вот и скажи, зачем.

      Delete
    9. по настроению пишу. там обсуждать особо нескем и правда

      Delete
    10. Ну настроение бывает часто, там я видел почти все интересное, что у тебя есть, так что насчет плебейского руского ты сам себя опустил :)

      А по теме что можешь сказать?

      Delete
    11. ну я туда пишу то что проще всего объяснить с нуля. по какой теме, какой вопрсо?

      Delete
    12. >Сейчас проверил на mail.ru (javascript:alert(mailbox__password.value)) - почему-то не работает.

      Delete
  18. In chromium 34 there at least seems to be evidence of protection against reading autofilled passwords when a window is opened as a "child" of another. This prevents UXSS attacks from leaking passwords (iframed site never get their passwords autofilled). From the console you can read the input's value just fine, but javascript included in the page or injected later (via uxss) just returns "". Additionally, the form can not be submit() by javascript, [type=password] can't be changed to text, and cloneNode does not preserve the value.

    ReplyDelete
    Replies
    1. good, but i am sure that is not ultimate protection. What if i open a child window with my XSS, replace its opener with login page and then get access to password from child window.

      Delete
    2. No luck with the relaced parent window, but good thinking. Chromium has some sort of protection here, I believe the user must manually navigate or interact with the page in order for autofilled passwords to be accessible.

      Here is the uxss PoC I was playing with, if you want to test (works in chromium 34). xdomain:8889/login5.html serves a page where I've saved a password, and has a script that calls the "$" global function after a delay of 500ms:

      https://gist.github.com/anonymous/f6b97407d4108a034557

      Delete