views:

65

answers:

2

Long story short: on Chrome and Safari only, values from a login form are sometimes pasted into the user's URL, even though the actual login is POSTed via AJAX.

http://my-site.example/?name=user&pw=xxx&challenge=b1be8ad7aac242...

It's been reported repeatedly and I've seen it happen myself, but have been unable to reproduce it myself, much less figure out what on earth is going on. Here's what the login form boils down to:

<form name="login">
  <input type="Text" name="name">
  <input type="password" name="pw">
  <input type="hidden" name="challenge">
  <input type="button" onclick='JavaScript:xmlhttpPost("/php/login.php")'>
</form>

The actual POSTed request does not even contain the challenge parameter:

function xmlhttpPost(strURL) {
  if (window.XMLHttpRequest) {
    self.xmlHttpReq = new XMLHttpRequest();
  } else if (window.ActiveXObject) {
    self.xmlHttpReq = new ActiveXObject("Microsoft.XMLHTTP");
  }
  self.xmlHttpReq.open('POST', strURL, true);
  ...
  query = 'name=' + encodeURIComponent(name) + '&pw=' + encodeURIComponent(hash) + '&lpw=' + encodeURIComponent(legacy_hash);
  self.xmlHttpReq.send(query);
}

And on successful login, the user is redirected back to the same page (= forced to reload) if and only if they have a different language setting from the default:

location.href = "http://" + location.host + location.pathname;

Any ideas?

+4  A: 

Iin the cases you describe, the form actually gets posted, probably because the user has Javascript turned off or a script error occurs in xmlhttpPost.

The form will get sent as a GET request in some browsers because you don't specify a method property. (I think GET is the correct default per the standard, but some browsers deviate from this). Thus, the form data will end up in the URL.

Give the form a method="POST": That will fix the password data in URLs part.

Pekka
But wouldn't that still send the password in the clear, only as an POST instead of a GET?To clarify here, the values in the form are never meant to be setn out, they're just there so JavaScript can compute hashes etc. I should probably just rip out the <form> tags entirely and deal with them as individual fields...
jpatokal
@jpatokal if you don't want the form to degrade gracefully for non-Javascript browsers, removing the `form` probably is the best idea. You're bound to have problems like this otherwise.
Pekka
A: 

You know what I hate most about Stack Overflow? The fact that, by making you lay out even your most intractable problems in as simple and reduced a form as possible, you often stumble into the solutions yourself, usually about 5 seconds after submitting.

This time, it turns out that pressing ENTER was causing Safari/Chrome (Webkit) to submit the form and stick the parameters in the URL. The cure was simple:

<form name="login" onSubmit='JavaScript:return false;'>

And a tip o' the hat here:

http://stackoverflow.com/questions/751702/how-can-i-prevent-webkit-browser-to-submit-a-form-when-enter-is-pressed-in-an-inp

jpatokal
This is not really the solution. It will still post the login data into the URL when Javascript is turned off.
Pekka
Why not handle the submit event so that a user can click Enter to login?
ZippyV
@ZippyV: I already have a JavaScript key press hook for snagging both Enter and Tab in any browser, but apparently Chrome/Safari's submit hook is executed first.
jpatokal