Password Reset Vulnerability (Poisoning)

Most web application security vulnerabilities leverage user interaction in ways that were not initially intended by their developers. Password reset poisoning is one such vulnerability that leverages headers, such as the Host header in an HTTP request:

GET https://example.com/reset.php?email=foo@bar.com HTTP/1.1
Host: evilhost.com

Notice that the server name in the URL (example.com) is different from a malicious hostname in the Host header (evilhost.com).

Example of a Password Recovery Mechanism

One common functionality in most web applications is the ability to reset the user’s password. The user clicks a Forgot password link and the server sends a password reset link to the email account configured for the user account. The link includes a one time token and allows the user to set a new password without having to specify the old one.

Part of building that link is deciding what the domain should be. In PHP, this may look as follows:

$resetPasswordURL = "https://{$_SERVER['HTTP_HOST']}/reset-password.php?token=12345678-1234-1234-1234-12345678901";

This URL is then injected into a password reset email template and sent to the user. Developers expect $_SERVER['HTTP_HOST'] to be example.com, so they rarely perform any additional sanity checks on the input.

Targeted Attack

If a malicious actor wants to take control of a particular individual’s account, they can leverage password reset poisoning in the following way:

  1. Obtain the target’s email address used on the site. This is usually done via:
    1. Social engineering attacks (phishing, smishing, etc.)
    2. OSINT (open-source intelligence)
    3. Mining old data breaches for user information
  2. Send a password reset request on behalf of the target using a modified Host header, for example: 
    POST https://example.com/reset.php HTTP/1.1
    Accept: */*
    Content-Type: application/json
    Host: evilhost.com
    

    The reset password URL becomes:

    https://evilhost.com/reset-password.php?token=12345678-1234-1234-1234-12345678901
    
  3. Wait for the target to receive the manipulated email: 

    Password Reset Poisoning

    Such emails would look entirely secure to the user, especially if the link is hidden behind a button or image. This is primarily due to the fact that the email is actually sent by the correct application and not the attacker-controlled host.

  4. After the user clicks the link, the attacker extracts the victim’s password reset token. At this point, the attack can go a step further by cloning the site to make it seem as though the user is accessing the legitimate one. This is generally done in one of two ways:
    1. The attacker clones part of the application (e.g. login page) and presents that to the user once they have clicked the link.
    2. The attacker’s site (evilhost.com) acts as a proxy to the real site whereby the behavior and the contents would be identical to the original site, making everything look seamless to the end-user. This is the most convincing method.

Remediation

From a development perspective, do not trust the Host header or any input header for that matter. Instead, the application base URL should be determined by configuration depending on the environment. A good example is a config.ini file such as:

[GLOBAL]
DB_URL=mysql://
DB_USER=root
DB_PASS=toor
 
[APPLICATION]
BASE_URL=example.com

This can then be string-interpolated safely as a constant in the previous code. You can use a utility function, for example, get_config(section, entry):

$resetPasswordURL = "https://" . get_config('APPLICATION', 'BASE_URL') . "/reset-password.php?token=12345678-1234-1234-1234-12345678901";

Additionally, as an application developer, you should support and highly incentivize multi-factor authentication to avoid malicious actors hijacking accounts with password reset tokens alone. Ideally, also avoid 2FA methods such as SMS Authentication.

Conclusion

Password reset poisoning is an attack that appears very trivial and is often used as low-hanging fruit in bug bounty programs. That said, it is very easy to secure against and illustrates why you should always be cautious of any possible form of user input. This is especially true if your information security team uses cybersecurity tools such as web application security scanners to automatically detect such vulnerabilities. Acunetix will not only test the Host header for password reset poisoning but it will also test for a slew of other Host header attacks to help you fully protect your web applications against the consequences of many different security issues.

Share this post
Acunetix

Acunetix developers and tech agents regularly contribute to the blog. All the Acunetix developers come with years of experience in the web security sphere.