Web cache poisoning via an unkeyed query parameter

Description

This lab is vulnerable to web cache poisoning because it excludes a certain parameter from the cache key. A user regularly visits this site’s home page using Chrome.

Reproduction and proof of concept

  1. Observe that the home page is a suitable cache oracle. Notice that you get a cache miss whenever you change the query string. This indicates that it is part of the cache key. Also notice that the query string is reflected in the response.

  2. Add a cache-buster query parameter.

  3. Use Param Miner’s Guess GET parameters feature to identify that the parameter utm_content is supported by the application.

  4. Confirm that this parameter is unkeyed by adding it to the query string and checking that you still get a cache hit. Keep sending the request until you get a cache miss. Observe that this unkeyed parameter is also reflected in the response along with the rest of the query string.

  5. Send a request with a utm_content parameter that breaks out of the reflected string and injects an XSS payload:

GET /?utm_content='/><script>alert(1)</script>
  1. Once your payload is cached, remove the utm_content parameter, right-click on the request, and select “Copy URL”. Open this URL in your browser and check that the alert() is triggered when you load the page.

  2. Remove your cache buster, re-add the utm_content parameter with your payload, and replay the request until the cache is poisoned for normal users. The lab will be solved when the victim user visits the poisoned home page

Exploitability

An attacker will need to poison the cache with a response that executes alert(1) in the victim’s browser.