Skip to content

Host header injection & insecure password-reset link (magic link uses untrusted req.headers.host + http) leading to account takeover #554

@bugdotexe

Description

@bugdotexe

Hello,My name is Nyein Chan Aung and I am a bug bounty hunter from Myanmar,I have identified a critical vulnerability that is affected to latest version of this product.Can we assign a CVE for this Vulnerability and resolve together?.
You can contact me here bugdotexe@wearehackerone.com

Description

Host header injection & insecure password-reset link (magic link uses untrusted req.headers.host + http) leading to account takeover

Vulnerability Type: Host header injection → password-reset link poisoning (magic link uses untrusted req.headers.host + http)

CVSS v4 Estimated Severity: 8.2 (High)Estimated score; see Impact Analysis.

Date: 2025-09-19


1. Executive summary

  • Vulnerable code:
mailer.sendFromTemplate({
      template: 'forgotPassword',
      user: user,
      token: token,
      host: req.headers.host,
      protocol: req.protocol,
      acceptLanguage: req.headers['accept-language']
    }, callback);
  }
  • Issue: The application builds absolute password-reset (magic) links using the untrusted req.headers.host header and forces the http:// scheme. An attacker who can control the Host header (or exploit a misconfigured proxy/load-balancer that forwards the header unchanged) can cause reset links to point to attacker-controlled domains or be delivered via insecure HTTP, enabling token theft, phishing, and account takeover.

  • Immediate risk: High — exposure or interception of reset tokens can lead to account takeover and credential theft.

  • Suggested immediate action: Stop using req.headers.host to build absolute links. Use a configured canonical base URL that includes https:// (e.g., BASE_URL=https://app.example.com).


2. Affected components

  • Password-reset / magic-link generation logic.

  • Email templates that include the magic-link.

  • Any proxy, load balancer, or gateway that forwards Host headers without validation.

  • Any other code paths that use req.headers.host to generate links or redirects.


3. Discovery details

  • During code review the application was observed building the magic link directly from req.headers.host and string-concatenating with http://.

  • req.headers.host can be controlled by an attacker who can send requests to the application (or to an intermediary that forwards headers unchanged). If an email containing the magic link is generated based on such a request, the email may contain an attacker-controlled domain.

  • Because the link is absolute and uses plaintext HTTP, an attacker can:

    • Host a domain that receives token-bearing links and capture the token.

    • Phish users with a page that looks like the real reset page but forwards token and credentials to the attacker.

    • Intercept tokens on insecure networks (HTTP downgrade).


4. Proof-of-Concept (non-exploitative)

This PoC shows how an attacker-supplied Host header could result in an email that includes an attacker domain. Do not use this to target real accounts without authorization.

# Attacker triggers password-reset email while supplying a fake Host header

curl -s -X POST "https://note-vault.app/reset-password/${resetToken}" \

  -H "Host: attacker.example.net" \

  -d "email=victim@example.com"

The password reset email will contain a link like:


http://attacker.example.net/reset-password/{token}

An attacker controlling attacker.example.net can collect the token or present a phishing UI that extracts credentials or the token when victims click the link.


5. Impact analysis

Confidentiality

  • High. Reset tokens embedded in attacker-controlled links are easily exfiltrated by the attacker-controlled domain or intercepted over HTTP.

Integrity

  • High. With a reset token an attacker can set a new password and take over the account (full account compromise).

Availability

  • Low–Medium. Not typically an availability issue, but large-scale account takeover can lead to operational impacts.

Attack scenarios

  • Targeted account takeover: Attacker causes a reset email for a specific victim and captures the token.

  • Mass phishing: Attacker poisons links in mass reset flows or in cached pages to harvest tokens or credentials.

  • Network interception: Forcing http:// allows MITM on untrusted networks to observe tokens.


6. Root cause

  • Trusting a client-controlled header (req.headers.host) when generating absolute URLs.

  • Hardcoding the insecure scheme http:// rather than using https:// or a configurable canonical origin.

  • Lack of allowlist validation for allowed hostnames or lack of a server-side canonical base URL configuration.


7. Remediation (actionable steps)

High-priority (apply immediately)

  1. Stop using req.headers.host to build absolute links.

    Use a server-side configured canonical base URL stored in configuration/environment, and include the scheme (must be https://).

    • Recommended env var: BASE_URL=https://app.example.com
  2. Always generate HTTPS links.

    Ensure the base URL uses https:// and that emails/links use https://.... Do not generate http:// links for public-facing flows.

  3. Make tokens single-use and short-lived.

    • Token TTL: e.g., ≤ 1 hour (adjust to risk model).

    • Invalidate token after first use.

    • Record token issuance timestamp and revoke after expiry.

Example secure replacement (Node.js / Express)

// config.js

module.exports = {

  BASE_URL: process.env.BASE_URL || 'https://app.example.com', // MUST include https://

  RESET_TOKEN_TTL_SECONDS: 3600,

};



// reset-email.js

const { BASE_URL } = require('./config');

const { URL } = require('url');



function buildResetLink(token) {

  // Safe: uses canonical BASE_URL, avoids req.headers.host

  return new URL(`/reset-password/token/${encodeURIComponent(token)}`, BASE_URL).toString();

}

If multi-tenant dynamic hosts are required

  • Maintain a server-side allowlist mapping inbound Host values to canonical origins and only use allowlisted hosts to build links.
const allowedHosts = {

  'tenant1.example.com': 'https://tenant1.example.com',

  'tenant2.example.com': 'https://tenant2.example.com',

};

const rawHost = req.headers.host?.split(':')[0]; // strip port

const BASE_URL = allowedHosts[rawHost] || process.env.BASE_URL;

const magicLink = new URL(`/reset-password/token/${token}`, BASE_URL).toString();

Additional hardening

  • Use short, unpredictable tokens (cryptographically secure random values, not predictable sequential IDs).

  • Consider server-side reference codes: email includes a short code that your server maps to a token without exposing raw token in the URL when possible.

  • Add logging and alerting for suspicious Host header values and unusual reset request patterns.

  • Audit and correct proxy/load-balancer configuration to canonicalize or strip client Host headers where appropriate.


9. Remediation timeline & priorities

  • Immediate (0–72 hours):

    • Replace req.headers.host usage with BASE_URL config and ensure https://.

    • Shorten token TTL and enforce single-use.

  • Short term (1 week):

    • Audit codebase for other req.headers.host / client-header usage.

    • Add host allowlist logic if multi-tenant hostnames are expected.

  • Medium term (1 month):

    • Add monitoring/alerting on suspicious Host headers and mass reset events.

    • Run targeted pentests / red-team to validate fixes.

  • Long term:

    • Review other flows that generate absolute URLs (email invites, webhooks) and standardize on the BASE_URL approach.

    • Harden proxy/load-balancer canonicalization.


10. Suggested disclosure notes for triage

  • This is an authentication-related vulnerability with high impact; treat as high priority.

  • Include remediation steps and request confirmation once the canonical base URL config and deployment changes are applied.

  • Ask security/ops team to audit proxies/load-balancers for header forwarding behavior.


11. References & further reading

  • OWASP — Host header attack guidance and mitigation (search OWASP for “Host header” or “Host header poisoning”).

  • OWASP — Authentication Cheat Sheet / Password Reset Guidance (search OWASP Authentication Cheat Sheet and Password Reset).

  • Node.js URL class (safe URL construction).

  • General best-practices for password reset tokens: single-use, short TTL, cryptographically random values, and server-side lookup rather than exposing persistent secrets.

E

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions