Bug Hunting Journey

Writeups Info leak

Info leak

Adding .css to a settings page and getting someone else's

Severity High CVSS 7.4
Impact
Account details of other users served from cache
Bounty
$1k - $2.5k
Program
Private

TL;DR

The edge cache keyed on the file extension and the origin on the route prefix. A URL ending in .css was cached as a static asset while the origin returned the authenticated account page, which then got served to whoever asked for the same URL.

Web cache deception needs two components that disagree about what a URL means. Here the CDN read the end of the path and the origin read the beginning, and nobody owned the middle.

The disagreement

GETRequestrequest
GET /account/settings/anything.css HTTP/2Host: app.target.tldCookie: session=████████████████
200OKresponse
HTTP/2 200 OKcontent-type: text/html; charset=utf-8cache-control: public, max-age=600x-cache: MISS

Two things are wrong in that response. The origin served the HTML account page despite the .css suffix, because its router matches on the /account/settings prefix and ignores the rest. And the edge rewrote Cache-Control to public because the extension matched its static asset rule.

Ten minutes later, the same URL fetched with no cookies at all:

200OKresponse
HTTP/2 200 OKcontent-type: text/html; charset=utf-8x-cache: HIT<h1>Account settings</h1><div class="email">████████████████</div>

Exploitation

The victim does not have to click anything unusual. Any link to app.target.tld/account/settings/x.css works: the first authenticated person to load it fills the cache, and everyone after that reads their page.

Takeaways

  • The cache key and the routing rule must agree on what identifies a page. Here one looked at the suffix and the other at the prefix.
  • An origin that ignores trailing path segments is the real bug. The CDN rule only makes it exploitable.
  • Never let the edge upgrade a response to public. The origin owns cacheability, and authenticated responses should carry private explicitly.

Disclosure timeline

  1. Report sent
  2. Emergency mitigation caching disabled on the account prefix
  3. Fix deployed
  4. Cleared for publication