Some vulnerabilities are elegant in how simple they are. No complex exploit chain. No stack of dependencies. Just one wrong assumption in the code — "I can trust the Host header the client sends me" — and suddenly the attacker controls where your session cookies live.

This is that finding.

What Is Host Header Injection

When your browser makes a request, it sends a Host header telling the server which domain it is talking to. Servers use this for routing, virtual hosting, and occasionally — incorrectly — for generating URLs and setting cookie attributes.

The Domain attribute in a cookie defines which domains the browser will send that cookie to. If a server sets Domain=example.com, the browser sends that cookie to example.com and all its subdomains.

The vulnerability happens when a server reads the Host header from the request and uses it directly to set the cookie Domain — without any validation. An attacker who can control the Host header can control where the cookie is sent.

The Finding

The target API endpoint was vulnerable to exactly this. Here is the entire proof of concept — nothing fancy, just curl.

Step 1 — Normal behavior

bash

curl -sk https://[target-api]/ -D - -o /dev/null | grep -i domain

Response:

Domain=apix.[redacted].om

Normal. The cookie domain matches the actual server domain.

Step 2 — Inject a custom Host header

bash

curl -sk https://[target-api]/ \
  -H "Host: attacker.com" \
  -D - -o /dev/null | grep -i domain

Response:

Domain=attacker.com

The server read the Host header value and used it directly to set the cookie domain. No validation. No whitelist check. Whatever you put in the header, the server puts in the cookie.

Step 3 — Set parent domain for wildcard scope

bash

curl -sk https://[target-api]/ \
  -H "Host: .[redacted].om" \
  -D - -o /dev/null | grep -i domain

Response:

Domain=.[redacted].om

Now the cookie is valid across every subdomain on the platform. If any subdomain has an XSS vulnerability, it can read session cookies from users across the entire domain.

Step 4 — Multiple Host headers bypass

This is the interesting part. Most developers assume that if the request reaches the correct server, the Host header must be legitimate. But:

bash

curl -sk https://[target-api]/ \
  -H "Host: attacker.com" \
  -H "Host: apix.[redacted].om" \
  -D - -o /dev/null | grep -i domain

Response:

Domain=attacker.com

The request is processed normally — the server routes it correctly using the second Host header. But when setting the cookie domain, it uses the first one. The request looks legitimate to any middleware or WAF checking for the correct Host, but the cookie still gets scoped to attacker.com.

The Attack Scenario

Here is how this turns into session hijacking in practice:

An attacker crafts a link or embeds a request that causes the victim's browser to hit the vulnerable endpoint. The server responds with a session cookie scoped to attacker.com. When the victim later visits attacker.com — or is redirected there — the browser automatically sends the cookie. The attacker captures it and replays it against the target application to access the victim's account.

The parent domain variant is worse. Setting Domain=.[redacted].om makes the cookie valid across every subdomain. Combined with an XSS on any subdomain — even a low-severity one — an attacker can harvest session cookies from authenticated users across the entire platform.

Root Cause

Three things went wrong simultaneously:

The application trusts the Host header as a source of truth for the cookie domain — user-controlled input used in a security-sensitive operation.

No validation or whitelist is applied — any value in the Host header is accepted and reflected into the cookie.

Multiple Host headers are handled inconsistently — different parts of the application read different headers, creating a bypass for any middleware-level checks.

Remediation

Hardcode the cookie domain. Never derive it from request headers. The domain should be a constant defined in server configuration — not read from user input.

Reject requests with multiple Host headers. HTTP/1.1 does not allow multiple Host headers. A request with more than one is malformed and should be rejected at the server or reverse proxy level.

Validate the Host header against a whitelist. If the Host header is used for any purpose, validate it against a list of known legitimate domains before using it.

python

ALLOWED_HOSTS = ["apix.example.com", "api.example.com"]
def get_cookie_domain(request):
    # Never do this
    # return request.headers.get("Host")
    # Always do this
    return "apix.example.com"

Takeaway for Hunters

Host header injection is consistently underreported because it requires understanding the downstream impact — just reflecting a header is not enough, you need to show what the attacker can do with it.

The key is finding where the Host header value ends up. Common injection points beyond cookies:

Password reset links — if the reset email is generated using the Host header, an attacker can redirect the reset link to their own domain and capture the token.

Cache poisoning — if a CDN caches responses keyed by Host, injecting a different host can poison the cache for other users.

SSRF — if the Host header is used in server-side requests, injecting an internal hostname can turn it into an SSRF.

Always trace the value. The header itself is just the entry point.

Bug Type: Host Header Injection → Session Cookie Domain Manipulation Severity: Medium Reward: $100 Platform: HackerOne Authentication Required: None Method: curl — no special tools required

Tags: Bug Bounty API Security Cybersecurity Ethical Hacking Web Security