Have you ever thought of testing for CSRF vulnerability on a password reset link? You might not have, because we generally believe that it is not possible, as the password reset link itself contains a reset token which acts as an alternative for a CSRF token.
I, too, once shared this assumption, but recently I encountered a CSRF vulnerability on a password reset link on a popular site. Since the vulnerability is still not patched, let's refer to it as
https://target.com
.Generally, the password reset link works in 2 different ways:
- The password reset link is itself
https://example.com/reset-password/secretToken
& upon changing the password, a POST request will be sent along with the token that is reflected in the URL.
1POST /reset-password?secretToken=tokenHTTP/2
2Host: account.example.com
3
4password=spandanpokh&password_confirm=spandanpokh
- The password reset link
https://example.com/reset-password/secretToken
redirects 302 tohttps://account.example.com/reset-password?redirect=https%3A%2F%2Faccount.example.com%2Freset-password%2Fsteps&mode=reset-password
& then it allows us to change our password. Here also token will be sent in an HTTP request.
1POST /reset-password?redirect=https%3A%2F%2Faccount.example.com%2Freset-password%2Fsteps&mode=reset-password HTTP/2
2Host: account.example.com
3
4secretToken=token&password=%40Helloworld1&password_confirm=%40Helloworld1
Since it is a password reset link, a reset token will definitely be present in the HTTP request and we think that it is impossible to perform CSRF. Well, in my case it was a bit different.
In my case as well, the reset link
https://target.com/reset-password/79xldx5d0h1gxwxfgw75oobhiff34tmibh9fut9roj5ht
was returning 302
and redirecting to https://account.target.com/reset-password?redirect=https%3A%2F%2Faccount.target.com%2Freset-password%2Fsteps&mode=reset-password
However, upon changing the password, I noticed that the reset token was neither reflected on the URL nor on the body of the HTTP request.
1POST /reset-password?redirect=https%3A%2F%2Faccount.target.com%2Freset-password%2Fsteps&mode=reset-password HTTP/2
2Host: account.target.com
3Cookie:
4
5password=%40Helloworld1&password_confirm=%40Helloworld1
Since there was no reset token on the HTTP request, I was thinking how is the server validating the request then? In that HTTP request, there were a lot of encoded cookies, and I immediately started decoding all those cookies.
Notice the redirect_url parameter on cookies.
Decoding the value: