Web Cache Poisoning to Exploit a DOM Vulnerability via a Cache with Strict Cacheability Criteria
Vulnerability Summary
This lab demonstrates a web cache poisoning attack that exploits a DOM-based XSS vulnerabilitythrough a cache with strict criteria.
The application's home page uses a DOM-based vulnerability in its JavaScript, which fetches a JSON file to determine shipping information. The cache, however, has strict rules and does not cache the home page by default. An attacker can use a cache buster (a unique query parameter) to force the cache to treat each request as unique, making it cacheable. By identifying a hidden header (X-Forwarded-Host
) as a cache key, an attacker can poison the cache with a malicious X-Forwarded-Host
header pointing to their exploit server. This causes the victim's browser to fetch a malicious JSON file containing a DOM-based XSS payload, which is then executed in the victim's browser.
Key Issues:
- The application uses a DOM-based XSS vulnerability that can be exploited via a JSON file.
- A cache buster is required to make the home page cacheable.
- A hidden header (
X-Forwarded-Host
) is used as a cache key. - An attacker can poison the cache with a malicious header that points to an exploit server.
Takeaway: Web caches can be a powerful tool for attackers. A cache can be poisoned by manipulating unkeyed headers. To prevent this, ensure that all cacheable requests are treated consistently, regardless of headers or parameters. All user input should be sanitized, and DOM-based vulnerabilities should be prevented.
Link to the Portswigger Lab
Lab Description
This lab contains a DOM-based vulnerability that can be exploited as part of a web cache poisoning attack. A user visits the home page roughly once a minute. Note that the cache used by this lab has stricter criteria for deciding which responses are cacheable, so you will need to study the cache behavior closely.
To solve the lab, poison the cache with a response that executes
alert(document.cookie)
in the visitor's browser.
Step-by-Step Guide
1. Analyze Cache Behavior and Find a Hidden Header: Visit the homepage and examine the GET /
request in Burp Proxy's HTTP history
. The X-Cache: hit
response header confirms that the page is cached. Send the request to Repeater. Use a tool like Param Miner to find hidden headers and discover that X-Forwarded-Host
is an unkeyed header.
2. Craft a Malicious JSON File: Go to the Exploit Server. Create a file at the path /resources/json/geolocate.json
with the following content. This payload contains a DOM-based XSS vulnerability. Add the Access-Control-Allow-Origin: *
header to enable CORS. Store the file.
{
"country": "<img src=1 onerror=alert(document.cookie) />"
}
3. Poison the Cache: In Repeater, add a cache buster to the URL (e.g., /?cachebuster=1
) and the X-Forwarded-Host
header pointing to your Exploit Server. Send the request twice. The X-Cache: hit
response header on the second request confirms that the cache has been poisoned.
4. Wait for the Victim: Remove the cache buster and wait for the victim to visit the homepage. When the victim's browser loads the poisoned page, it will fetch the malicious JSON file from your Exploit Server, and the XSS payload will execute, solving the lab.
Combining Web Cache Poisoning Vulnerabilities
Vulnerability Summary
This lab demonstrates a complex web cache poisoning attack that chains multiple vulnerabilities, including DOM-based XSS and unkeyed headers, to achieve a final exploit.
The application uses an allow-list for the X-Forwarded-Host
header, but this can be bypassed by combining it with another vulnerability. The application also uses an unkeyed X-Original-Url
header that allows an attacker to manipulate the request path. By first using the X-Original-Url
header to redirect the victim to the Spanish version of the website, an attacker can then use the X-Forwarded-Host
header to poison the cache with a malicious JSON file containing a DOM-based XSS payload. This allows the attacker to exploit the victim's browser and solve the lab.
Key Issues:
- The application is vulnerable to web cache poisoning via multiple unkeyed headers.
- A DOM-based XSS vulnerability exists in the translation function.
- The attack requires chaining two different cache poisoning techniques to work.
Takeaway: A comprehensive defense against web cache poisoning requires a holistic approach. Do not rely on a single defense mechanism. All headers and parameters that are not part of the cache key should be stripped or sanitized.
Link to the Portswigger Lab
Lab Description
This lab is susceptible to web cache poisoning, but only if you construct a complex exploit chain.
A user visits the home page roughly once a minute and their language is set to English. To solve this lab, poison the cache with a response that executes
alert(document.cookie)
in the visitor's browser.
Step-by-Step Guide
1. Analyze Cache Behavior and Find Hidden Headers: Visit the homepage and examine the GET /
request in Burp Proxy's HTTP history
. The X-Cache: hit
response header confirms that the page is cached. Send the request to Repeater. Use a tool like Param Miner to find hidden headers and discover that X-Forwarded-Host
and X-Original-Url
are unkeyed.
2. Craft a Malicious JSON File: Go to the Exploit Server. Create a file at the path /resources/json/translations.json
with the following content. This payload contains a DOM-based XSS vulnerability. Add the Access-Control-Allow-Origin: *
header to enable CORS. Store the file.
{
"en": {
"name": "English"
},
"es": {
"name": "español",
"translations": {
"Return to list": "Volver a la lista",
"View details": "</a><img src=1 onerror='alert(document.cookie)' />",
"Description:": "Descripción"
}
}
}
3. Exploit X-Forwarded-Host
and X-Original-Url
: In Repeater, first poison the cache for the Spanish version of the website.
- Send the
GET
request with a cache buster (/?cb=1
) and theX-Forwarded-Host
header pointing to your Exploit Server. Send the request twice to get anX-Cache: hit
. - Now, poison the cache for the English version. Send the
GET
request (with a cache buster) and theX-Original-Url
header with the value/setlang\es
. This redirects the victim to the Spanish version of the website. Send the request twice to get anX-Cache: hit
.
4. Wait for the Victim: Remove the cache busters and wait for the victim to visit the homepage. When the victim's browser loads the poisoned page, it will be redirected to the Spanish version of the website and fetch the malicious JSON file from your Exploit Server. The XSS payload will then execute, solving the lab.
Cache Key Injection
Vulnerability Summary
This lab demonstrates a cache key injection vulnerability that allows an attacker to inject an HTTP header into a cached response.
The application uses an unkeyed parameter (utm_content
) in the URL, which is not part of the cache key. An attacker can use this parameter to inject a malicious payload into the response. The attacker can then use a different vulnerability, such as a response header injection via the Origin
header, to inject an alert
payload into the response. The injected payload is then cached and served to the victim, who then executes the payload. This is a complex attack that combines multiple vulnerabilities to achieve a final exploit.
Key Issues:
- The application uses an unkeyed parameter in the URL.
- An attacker can inject a payload into the response via a response header injection.
- The injected payload is cached and served to the victim.
Takeaway: Web caches can be a powerful tool for attackers. To prevent this, ensure that all headers and parameters that are not part of the cache key are stripped or sanitized.
Link to the Portswigger Lab
Lab Description
This lab contains multiple independent vulnerabilities, including cache key injection. A user regularly visits this site's home page using Chrome.
To solve the lab, combine the vulnerabilities to execute
alert(1)
in the victim's browser. Note that you will need to make use of thePragma: x-get-cache-key
header in order to solve this lab.
Step-by-Step Guide
1. Analyze Cache Behavior and Find Unkeyed Parameters: Send the GET /login?lang=en
request to Repeater. Use a tool like Param Miner to find hidden parameters and discover that utm_content
is an unkeyed parameter.
2. Craft a Malicious Payload: The vulnerability allows an attacker to inject a payload into the response via a response header injection. The payload will be alert(1)
.
3. Inject the Payload: Send the GET /js/localize.js?lang=en?utm_content=sl0th&cors=1&x=1
request to Repeater. Add the Origin
header with a malicious payload: Origin: x%0d%0aContent-Length:%208%0d%0a%0d%0aalert(1)$$$$
. Send the request twice.
4. Poison the Cache: In a second tab in Repeater, send the GET /login?lang=en?utm_content=x%26cors=1%26x=1$$origin=x%250d%250aContent-Length:%208%250d%250a%250d%250aalert(1)$$%23
request. Send the request until the X-Cache
header is set to hit
.
5. Wait for the Victim: Remove the cache buster and wait for the victim to visit the homepage. When the victim's browser loads the poisoned page, the alert(1)
payload will execute, solving the lab.
Internal Cache Poisoning
Vulnerability Summary
This lab demonstrates a web cache poisoning attack that targets an internal cache, leading to a full exploit.
The application uses multiple layers of caching, including an internal cache that can be poisoned by an attacker. The vulnerability lies in the fact that the application uses the X-Forwarded-Host
header to determine the location of a JavaScript file. An attacker can use this header to poison the internal cache with a malicious JavaScript file from their Exploit Server. When the victim's browser loads the poisoned page, it will fetch the malicious JavaScript file from the internal cache, and the XSS payload will execute, solving the lab.
Key Issues:
- The application uses multiple layers of caching.
- An attacker can poison the internal cache with a malicious JavaScript file.
- The
X-Forwarded-Host
header is an unkeyed header that can be used to poison the cache.
Takeaway: Internal caches can be a powerful tool for attackers. To prevent this, ensure that all headers and parameters that are not part of the cache key are stripped or sanitized.
Link to the Portswigger Lab
Lab Description
This lab is vulnerable to web cache poisoning. It uses multiple layers of caching. A user regularly visits this site's home page using Chrome.
To solve the lab, poison the internal cache so that the home page executes
alert(document.cookie)
in the victim's browser.
Step-by-Step Guide
1. Analyze Cache Behavior and Find Unkeyed Headers: Send the GET /
request to Repeater. Use a tool like Param Miner to find hidden headers and discover that X-Forwarded-Host
is an unkeyed parameter.
2. Craft a Malicious JavaScript File: Go to the Exploit Server. Create a file called /js/geolocate.js
and add the payload alert(document.cookie)
to the body. Store the file.
3. Poison the Internal Cache: In Repeater, add the X-Forwarded-Host
header with the value of your Exploit Server. Send the request. The website will search for the JavaScript file on your Exploit Server and cache it.
4. Wait for the Victim: Remove the X-Forwarded-Host
header and send the request. The website will now load the malicious JavaScript file from the internal cache. Wait for the victim to visit the homepage, and the alert(document.cookie)
payload will execute, solving the lab.