password reset poisoning via middleware

3 min read Easy PortSwigger
Authentication
Contents

On this page

The lab

here is how portswigger describes it

This lab is vulnerable to password reset poisoning. The user carlos will carelessly click on any links in emails that he receives. To solve the lab, log in to Carlos's account. You can log in to your own account using the following credentials: wiener:peter. Any emails sent to this account can be read via the email client on the exploit server.

the last two labs stole a cookie and cracked it. this one never touches carlos's password at all. instead we hijack the site's own password reset email and bend the reset link so that when carlos clicks it, the secret token meant to protect him comes to us.

a password reset usually works like this. you ask for a reset, the site generates a one time token tied to your account, and it emails you a link containing that token. clicking the link proves you own the inbox, and the token lets you set a new password. the token is the whole secret, so if an attacker ever learns a victim's token, they can reset that victim's password themselves.

the weakness here is in how the site decides what domain to put in that link. rather than using a fixed, trusted address, it builds the link's host from a header on the incoming request. the X-Forwarded-Host header is normally added by proxies and middleware to tell the back end which hostname the user originally asked for, and this app trusts it blindly when writing the reset url. so we can send a reset request for carlos while setting X-Forwarded-Host to our own server. the email still goes to carlos with his real token inside, but the link now points at us, and because carlos clicks anything, his browser hands that token straight to our server.

Step 1 - study the reset flow#

we open the forgot password feature and request a reset for our own account by entering wiener. the site replies that a reset link has been sent, so we check our email client and see the link arrive, built around our own token.

that gives us a known good reset request to tamper with, so we send the POST /forgot-password request to repeater.

Step 2 - poison the host with X-Forwarded-Host#

in repeater we test whether the app trusts the host header. we note our exploit server url, then add this header to the reset request:

X-Forwarded-Host: YOUR-EXPLOIT-SERVER-ID.exploit-server.net

then we change the username parameter from wiener to carlos and send it. the effect is a split one. the reset email is still delivered to carlos because the account is his, and it still contains his genuine one time token, but the clickable link in that email is now assembled using our hostname instead of the real site. carlos's token is being wrapped in a url that points at us.

Step 3 - catch carlos's token in the logs#

because carlos clicks any link he receives, he opens the poisoned link, and his browser makes a request to our exploit server carrying the token as part of the path.

we open the access log on the exploit server and find his request, and sitting in the url is the temp-forgot-password-token value that belongs to carlos. that token is the key to his account and it is now in our hands.

Step 4 - use the stolen token and solve#

we do not even need the poisoned link to be usable, we just needed the token out of it. so we go back to our own email client and take the legitimate reset link, the one pointing at the real site rather than our server, since that link actually reaches the password reset page.

we paste that real link into the browser and swap the temp-forgot-password-token value in it for the token we stole from carlos. that tells the real reset page we are completing carlos's reset, so it lets us set a new password on his account. with his password now ours, we log in as carlos.

with this, the lab is solved!