-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix token leakage #4366
Fix token leakage #4366
Conversation
ping |
The clearance gem had the exact same issue and this change is very similar to what ended up going into that recently. Theres a bit more of conversation here about the problem/fix that might be of interest to people here also - thoughtbot/clearance#707 |
@ethirajsrinivasan can you review pls? |
@icaruswings Sorry for the missed reply. Is that PR part of devise now? |
ping @ethirajsrinivasan |
@rafaelfranca @lucasmazza sorry to bug you, I'm not sure who else can help get this merged. We encountered the same problem and it would be great to get it fixed for everyone and not just in our app. Any thoughts? |
ping This security bug got reported to us, so it's great to see there's a PR that addresses it! Is there anything I can do to help get this through? |
I am getting no response from the devise team. Can someone review this please? |
Sorry about this, I've labeled this one and I'll definitely review it. Thanks. |
I think I discussed this with José some time ago. If I remember correctly this is only a problem if you allow third-party JavaScript code to be executed in your reset password page. If you does allow that, the token leaking in the Referer reader is only one of your problems. Please let me know if that is not the only case were this is a problem. |
@rafaelfranca This is a problem if there are any resources on the page (i.e. analytics tags, external JS, CSS, images, etc). In this screenshot, you can see in this request that the referrer contains the token. An attacker could then use the same URL to change the user's password |
Would the |
@lucasmazza I had the same thought, but when I put |
@stewartyu I used that thoughtbot piece to help guide this PR. So I believe this solution follows those best practices. |
Again, if you add external resources to your page and don't trust them you have a really big problem. This problem is similar to a MITM attack in your email account. If there is someone listening to your emails your reset password token will also be leaked. Of course, different from the MITM attack, it is the site owner that is installing the MITM against all the users accounts. In my opinion the proper fix for this issue is to only use trusted external resources in your reset password page. If you don't trust your external resources, leaking the reset token is just the beginning. They could be mining bitcoins in your clients machines, stealing their credit card information, passwords, session cookie (like this reset token that the PR is adding to the session). Of course we can narrow the attack surface with this change, but I'm not sure if it is worth to make this change given the real security issues is be still there. |
I was just reading this and I thought that there's 1 way to solve this problem, but not really know if it's worth it (instead of customising the rendering of the reset controller/action to use a clean layout without possibly dangerous external content) A solution would be to have the reset tied to the IP requesting the reset token. This involves two additional columns - reset_ip_request, visited (Default false) - and a special treatment of the request when not matching IPs
Second case:
On the first case the real user could still go again to reset the password because since the first visit with the token matched the IP's (assuming it's the user that has access to the email that executes always the first visit), This would mean that you would need to compromise the email box in order to be able to reset a password. |
@mnussbaumer I like your idea. Although the workflow for the second case is worst, for the first case we don't have an extra redirect like this current implementation. |
@rafaelfranca but there wouldn't be any redirect, and in the second case it would only happen if a) someone requested the reset for you, in which case the reset being "reseted" is not a problem b) you requested the reset from a device and then opened the reset link from another device. Both of these could have a message when they happened: "It seems you requested to reset this password from a different device than the one you're currently using. To be able to reset your password safely please make sure you do both steps from the same device. Click the following link to request a new reset link..." wtv? Perhaps it could be opt-in, :paranoid_resets. If this was something that could get merged I might look into making a PR? (I haven't really looked at the source so, this is assuming it's something doable without extreme pain) (edit: actually - if the problem is the token appearing on the referrer link, then it could be, instead of setting the ip on the request to reset, setting the ip on the first visit to the reset link - since that will most certainly be the real user, unless the email has been jacked, because the token won't be known until a) the user visits the link triggering the external assets load b) the app being jacked, c) the mailbox of the user being jacked) |
@mnussbaumer Are you willing to work on this? Otherwise we need to open an issue for it. |
The current implementation of the password reset page using a
reset token
leaves thereset token
in the url's query parameters, which run the risk of exposing it via theReferer
. This solution, grabs thereset token
, stores it in thesession
, and redirects the user to the reset password page (/edit) without thereset token
in the query parameters. We then delete thetoken
from thesession
on a successful update of the password.Tests updated and 2 new ones added.