I'm currently working on a WordPress plugin of my own that involves a custom login interface. I'm wondering, why is it that when you reset your password on WP-Admin, WordPress stores the reset password key in a cookie rather retrieve it from the URL through $_GET?

For example, if your reset link is https://example.com/wp-admin/?action=rp&key=123123213213213123&login=admin, the link will store $_GET['key'] and $_GET['login'] in a cookie and serve you this page using the cookie: https://example.com/wp-admin/?action=rp.

Are there any security reasons for doing that?

  • Yes. It's definitely because of security reasons – Wordpresskiller Jul 15 at 6:52
  • 1
    Why do you assume there is any answer which is more of a "because"?. Not every line of code has some deep thought behind it. – Mark Kaplun Jul 15 at 9:14
up vote 3 down vote accepted

To be honest? It's a little bit hard to say...

This behavior was introduced in 3.9.2 (which is security release). Here's the bug in Trac: 29060: Don't pass around the resetpass key, but there isn't much info on why was it introduced in the bug report.

Is it for security reasons? Most probably. But does it really make the process more secure? It's a little bit hard to say...

Both GET params and Cookies are sent in every request - so attacker still can intercept them. It just makes such attempts a little bit harder (since you have to get pass_key and it's hashed value).

  • 2
    This is a very long way to say "I do not know as well" ;). Upvoted because otherwise the question will keep poping up, while the only place to get an authoritative answer will be to ask nacin himself. – Mark Kaplun Jul 15 at 9:16
  • @MarkKaplun yes and no. There’s a question about that change in the bug report I’ve mentioned. It’s 22 months old now and still has no answer ;) It just makes MiM attacks a little bit harder, I guess... I don’t see any other reason for that in the code... – Krzysiek Dróżdż Jul 15 at 9:21
  • I don't know, maybe in 3.9 you had to do it to handle some actual security issue, but further changes in later releases made that change obsolete, and the only reason the code works now like it does is because no one felt like it needs to be changed again. So knowing the reason for the original change, might still not explain why it works like it does in 4.9. BTW I am pretty sure MiM has nothing to do with that, my guess is probably handling brute force attacks against the password reset – Mark Kaplun Jul 15 at 9:43
  • @MarkKaplun I guess using nonces would be the fix for BF attacks. This doesn't solve it - you can easily obtain hashed value from server and it doesn't get changed, so... It's sad that there is no docs for this bug/fix - Nacin just requested that change and that's all info you can find now... So I'm afraid, today, nobody knows/remembers why it is like so ;) – Krzysiek Dróżdż Jul 15 at 9:49
  • are you really blaming core in writing a correct code that actually solves correctly the issue? ;). I agree that this change is unlikely by itself to solve any problem (maybe only against very naive attacker). I also looked at CVEs and there is none relating to password resets in 3.9.1 that I could find – Mark Kaplun Jul 15 at 10:00

There is a couple of security benefits I can think of when you do it this way:

  1. If you go to the reset URL from your email, but forget to do the actual reset, someone having the visual access to your screen (either directly from behind you or from a security camera in front of you screen) has a higher chance of getting the reset URL from your browser address bar with the value of the key attribute. So setting it to Cookie & then redirecting to https://example.com/wp-login.php?action=rp helps in that regard.

  2. It keeps the browser history cleaner. Because of the redirect, key will not show up in the browser history. For example, you are using a little safer browser setting where Cookie is being cleaned after you close the browser window. With key in the browser URL, history may still keep it and someone may use it later without you knowing it (in case you've visited the link but didn't use it). So keeping the key in the Cookie & then redirecting helps in this case as well.

Granted, this is not the most extraordinary security enhancement, however, it's still an improvement (even if these are the only benefits you get from this update).

Note: I don't think this has any serious security benefit like fending off MITM attacks. MITM is same for GET & Cookie. Using HTTPS solves both.

  • 1
    1. Isn’t exactly true - it’s in the email, so it will get recorded ;) – Krzysiek Dróżdż Jul 15 at 11:26
  • 1
    LOL, yeah. But you can fix that by setting the URL in href ;) – Fayaz Jul 15 at 11:27
  • Well, any client still will show it. And it will be visible in the browser before the redirection happens ;) – Krzysiek Dróżdż Jul 15 at 11:29
  • ha ha, for fraction of a second. But it's still an improvement, no? – Fayaz Jul 15 at 11:30
  • if we’re talking about using recorders? That’s not an improvement - it still is visible, so will get recorded. It’s pretty hard to explain now, why that change was made, I guess... – Krzysiek Dróżdż Jul 15 at 11:32

I was wondering exactly the same. The best explanation I was able to find was here:

https://robots.thoughtbot.com/is-your-site-leaking-password-reset-links

If a user clicks the password reset link from an email and the full url is left in the browser, if they don't reset their password and click an out link on the password reset page, the full password reset link will be shared in the HTTP referer.

Admittedly, Wordpress does not have any out links on wp-login.php, but a lot of people customise this page and it's relatively easy to see the possible security concern.

Your Answer

 
discard

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.