Learn how combining X-Forwarded-Host and X-Original-URL vulnerabilities can poison web caches, delivering persistent XSS to unsuspecting users.

🔓 Free Link

Disclaimer: The techniques described in this document are intended solely for ethical use and educational purposes. Unauthorized use of these methods outside approved environments is strictly prohibited, as it is illegal, unethical, and may lead to severe consequences.

It is crucial to act responsibly, comply with all applicable laws, and adhere to established ethical guidelines. Any activity that exploits security vulnerabilities or compromises the safety, privacy, or integrity of others is strictly forbidden.

Table of Contents

  1. Summary of the Vulnerability
  2. Steps to Reproduce & Proof of Concept (PoC)
  3. Impact

Summary of the Vulnerability

This scenario demonstrates a web cache poisoning attack that relies on chaining two separate weaknesses: the X-Forwarded-Host and the X-Original-URL headers. Normally, web cache poisoning occurs when an attacker can manipulate the server's response in a way that gets stored in a caching layer, making the poisoned response delivered to other users.

In this lab, the server behavior creates a unique condition. The application fails to properly sanitize the X-Forwarded-Host header and also mishandles routing when X-Original-URL is supplied. Individually, neither issue alone results in a successful exploit. But when combined, they allow the attacker to modify cached responses in such a way that malicious JavaScript—alert(document.cookie) in this lab, executes in the victim's browser once the poisoned page is retrieved from cache.

Steps to Reproduce & Proof of Concept (PoC)

① Open the lab and observe the site's homepage requests in Burp HTTP History.

Image 1 — Combining Web Cache Poisoning with X-Forwarded-Host and X-Original-URL Headers
  • Notice the homepage GET / HTTP/2 always requests two resources:
1. ../translations.js
2. ../translations.json
Image 2 — Combining Web Cache Poisoning with X-Forwarded-Host and X-Original-URL Headers
Image 3 — Combining Web Cache Poisoning with X-Forwarded-Host and X-Original-URL Headers

② Start the attack workflow:

  • Make sure your Param Miner is activated.
Image 4 — Combining Web Cache Poisoning with X-Forwarded-Host and X-Original-URL Headers
  • Send the homepage request (GET /) to Repeater.
  • Right-click the request → ExtensionsParam MinerGuess headers.
Image 5 — Combining Web Cache Poisoning with X-Forwarded-Host and X-Original-URL Headers
  • Wait a few seconds for Param Miner to test likely headers.

③ Param Miner may surface manipulated headers such as:

1. X-Forwarded-Host
2. X-Original-URL
Image 6 — Combining Web Cache Poisoning with X-Forwarded-Host and X-Original-URL Headers
Image 7 — Combining Web Cache Poisoning with X-Forwarded-Host and X-Original-URL Headers

If Param Miner causes issues for you, disable/uncheck it. Since in some cases, my attack doesn't work if this extension still active, so I prefer disable it after finished scanning.

④ Test X-Forwarded-Host manually:

  • Add the header to the homepage request in Repeater:
X-Forwarded-Host: evil.com
  • Send the request and inspect the response. If the response reflects your domain and the Host value is changed, the application is echoing the header — a promising sign that you can control how the server constructs responses.
Image 8 — Combining Web Cache Poisoning with X-Forwarded-Host and X-Original-URL Headers

⑤ Identify language switch behavior:

  • Change the site language in the UI (English → Spanish).
Image 9 — Combining Web Cache Poisoning with X-Forwarded-Host and X-Original-URL Headers
Image 10 — Combining Web Cache Poisoning with X-Forwarded-Host and X-Original-URL Headers
  • Observe the language request in HTTP history:
GET /setlang/es?
→ redirected to /?localized=1
Cookie: lang=es
  • The /setlang flow sets lang=es and the redirect lands on /?localized=1.
Image 11 — Combining Web Cache Poisoning with X-Forwarded-Host and X-Original-URL Headers

⑥ Prepare the Exploit Server to host a malicious translations file:

  • On the Exploit Server, replicate the path used by the site:
/resources/json/translations.json
  • Ensure the server responds with the malicious JSON and add the header:
Access-Control-Allow-Origin: *

This bypasses CORS when the page fetches resources from your Exploit Server.

  • Place your payload where the page's UI pulls the translated string (for example the "View Details" string) so that when the language changes the DOM is controlled via /resources/js/translations.js.
Image 12 — Combining Web Cache Poisoning with X-Forwarded-Host and X-Original-URL Headers

⑦ Reflect your Exploit Server using X-Forwarded-Host:

  • Change X-Forwarded-Host to your Exploit Server hostname and send the homepage request repeatedly until the response reflects your Exploit Server domain.
Image 13 — Combining Web Cache Poisoning with X-Forwarded-Host and X-Original-URL Headers

⑧ Test in-browser rendering:

  • In Repeater, right-click the response → Show response in browser.
  • If the payload executes (e.g., alert(1)), you've successfully reflected the malicious resource.
Image 14 — Combining Web Cache Poisoning with X-Forwarded-Host and X-Original-URL Headers

⑨ Use X-Original-URL to force a cacheable redirect:

  • X-Original-URL can change the request path; try variations to trigger a redirect that becomes cacheable. Example attempts:
X-Original-Url: /setlang/es
X-Original-Url: \setlang\es
X-Original-Url: /setlang\es
Image 15 — Combining Web Cache Poisoning with X-Forwarded-Host and X-Original-URL Headers
  • In my testing, X-Original-Url: /setlang\es produced a 302 Found response and X-Cache: hit. The server normalized backslashes to forward slashes and treated the response as cacheable.
Image 16 — Combining Web Cache Poisoning with X-Forwarded-Host and X-Original-URL Headers

⑩ Construct the poisoning sequence (two-step chain):

  • Step A (poison reflective content): Send GET /?localized=1 with:
X-Forwarded-Host: <your-exploit-server>

This causes the localized response to reference your Exploit Server resource (the translations file with the payload).

  • Step B (cache the redirected homepage): Immediately send repeated GET / requests with:
X-Original-URL: /setlang\es

These requests trigger a redirect that the caching layer stores (X-Cache: hit), effectively poisoning the cached /?localized=1 content.

Image 17 — Combining Web Cache Poisoning with X-Forwarded-Host and X-Original-URL Headers
Image 18 — Combining Web Cache Poisoning with X-Forwarded-Host and X-Original-URL Headers

⑪ Verify exploitation:

  • After performing the sequence multiple times, open the homepage (with language defaulted to English). If poisoning succeeded, the page will load the cached malicious translations and execute the payload (e.g., an alert showing document.cookie).
  • Repeat refreshing and check browser behavior; once the popup triggers for a regular visitor, the lab is solved.

⑫ Finalize and store:

  • Update the Exploit Server payload to the final payload you want to test; click Store on the Exploit Server UI.
Image 19 — Combining Web Cache Poisoning with X-Forwarded-Host and X-Original-URL Headers
  • Re-run the poisoning sequence if needed until the exploit reliably triggers for an English-language visitor.
Image 20 — Combining Web Cache Poisoning with X-Forwarded-Host and X-Original-URL Headers
  • Confirm the lab is solved.
Image 21 — Combining Web Cache Poisoning with X-Forwarded-Host and X-Original-URL Headers

Impact

In production environments, this kind of chained cache poisoning vulnerability could be highly damaging. If an attacker manages to poison a cached response with malicious content, every subsequent user who loads that cached page will unknowingly execute the attacker's payload.

Potential consequences include Persistent cross-site scripting (XSS) — Since the payload remains in the cache until eviction, all visitors receive the malicious script.

📢 Enjoyed this post? Stay connected! If you found this article helpful or insightful, consider following me for more:

🙏Your support is appreciated.