Web Cache Deception Attack

Share this…

A few words about caching and reactions

  1. Websites often tend to use web cache functionality (for example over a CDN, a load balancer, or simply a reverse proxy). The purpose is simple: store files that are often retrieved, to reduce latency from the web server.

Let’s see an example of web cache. Website https://www.example.com is configured to go through a reverse proxy. A dynamic page that is stored on the server and returns personal content of users, such as https://www.example.com/home.php, will have to create it dynamically per user, since the data is different for each user. This kind of data, or at least its personalized parts, isn’t cached.

What’s more reasonable and common to cache are static, public files: style sheets (css), scripts (js), text files (txt), images (png, bmp, gif), etc. This makes sense because these files usually don’t contain any sensitive information. In addition, as can be found in various best practices articles about web cache configuration, it’s recommended to cache all static files that are meant to be public, and disregard their HTTP caching headers.

  1. The web cache deception attack counts on similar browsers’ and web servers’ reactions, in the same way as the RPO attack, explained in https://www.thespanner.co.uk/2014/03/21/rpo/ and https://blog.innerht.ml/rpo-gadgets/:

What happens when accessing a URL like https://www.example.com/home.php/non-existent.css?
A GET request to that URL will be produced by the browser. The interesting thing is the server’s reaction – how does it interpret the request URL? Depending on its technology and configuration (the URL structure might need to be built slightly different for different servers), the server returns the content of https://www.example.com/home.php. And yes, the URL remains https://www.example.com/home.php/non-existent.css. The HTTP headers will be the same as for accessing https://www.example.com/home.php directly: same caching headers and same content type (text/html, in this case).

Done with the introduction

What happens if we access https://www.example.com/home.php/non-existent.css, while web cache for static files is set on the proxy server, disregarding caching headers for this kind of file? Let’s analyze this process:

  1. Browser requests https://www.example.com/home.php/non-existent.css.
  2. Server returns the content of https://www.example.com/home.php, most probably with HTTP caching headers that instruct to not cache this page.
  3. The response goes through the proxy.
  4. The proxy identifies that the file has a css extension.
  5. Under the cache directory, the proxy creates a directory named home.php, and caches the imposter “CSS” file (non-existent.css) inside.

 

Oh.

Taking advantage of it

An attacker who lures a logged-on user to access https://www.example.com/home.php/logo.png will cause this page – containing the user’s personal content – to be cached and thus publicly-accessible. It could get even worse, if the body of the response contains (for some reason) the session identifier, security answers or CSRF tokens. All the attacker has to do now is to access this page on his own and expose this data.

An anecdote

Usually websites don’t require authentication to access their public static files. Therefore, the cached files are publicly-accessible – no authentication required.

Conditions

So basically, two conditions are required for this vulnerability to exist:

  1. Web cache functionality is set for the web application to cache files by their extensions, disregarding any caching header.
  2. When accessing a page like https://www.example.com/home.php/non-existent.css, the web server will return the content of “home.php” for that URL.

Mitigation

  1. Configure the cache mechanism to cache files only if their HTTP caching headers allow. That will solve the root cause of this issue.
  2. If the cache component provides the option, configure it to cache files by their content type.
  3. Configure the web server so that for pages such as https://www.example.com/home.php/non-existent.css, the web server doesn’t return the content of “home.php” with this URL. Instead, for example, the server should respond with a 404 or 302 response.

Web Cache Deception in PayPal – PII Exposure

PayPal was vulnerable to web cache deception. The vulnerability is now fixed and was publicly disclosed.

Information that could be leaked by exploiting this vulnerability:

– Users’ first & last names

– Account balance

– Last four credit card digits

– Transactions data

– Full passport number

– Email address

– Home address

– Phone number

– Any additional information included in vulnerable pages

Examples for some of the vulnerable pages:

– https://www.paypal.com/myaccount/home/attack.css

– https://www.paypal.com/myaccount/settings/notifications/attack.css

– https://history.paypal.com/cgi-bin/webscr/attack.css?cmd=_history-details


Various static file extensions could be used to cache pages on PayPal (more than 40). Among them:

aif, aiff, au, avi, bin, bmp, cab, carb, cct, cdf, class, css, doc, dcr, dtd, gcf, gff, gif, grv, hdml, hqx, ico, ini, jpeg, jpg, js, mov, mp3, nc, pct, ppc, pws, swa, swf, txt, vbs, w32, wav, wbmp, wml, wmlc, wmls, wmlsc, xsd, zip


Caching expiration

I’ve measured the time taken for the cached files to expire. It seems that after being accessed once (for the first time), a file is cached for ~5 hours. If it’s accessed again during that time, the expiration time is extended. It’s clear that this time period is more than enough for an attacker to “catch” the cached file on time before it expires, and by constantly monitoring this URL he can expose it as it’s created.

Videos

Home page:

https://www.paypal.com/myaccount/home

https://youtu.be/pLte7SomUB8

 

Settings page:

https://www.paypal.com/myaccount/settings

History page:

https://history.paypal.com/cgi-bin/webscr?cmd=_history-details

PayPal rewarded me with $3,000 for reporting this vulnerability.

User Hijacking via Web Cache Deception

I found this vulnerability in additional applications, which unfortunately cannot be disclosed to the public for different reasons (bummer, had some nice videos for that). In these applications, it was possible to take complete control over application users. This was possible because the session ID or security answers to recover a user’s password were included in the HTML code of vulnerable pages. Big thanks to Sagi Cohen for the assistance.

IIS Demo

In the video below, a website is hosted on two web servers behind an IIS load balancer with Application Request Routing (ARR) installed.
A successful login redirects the users to the ‘welcome.php’ page, which contains their personal content. The load balancer is configured to cache all CSS files, and to disregard their caching headers.

An authenticated user accesses https://www.sampleapp.com/welcome.php/stylesheet.css. The IIS load balancer refers to the ‘welcome.php’ page as a directory, creates it in the cache directory, and caches ‘stylsheet.css’, which contains the user’s private content.

Source:https://omergil.blogspot.in