dos-waf

// TL;DR


The ingredients

This bug comes from two normal, individually-harmless behaviours colliding:

  1. The site stores the referrer in a cookie. Lots of sites record where a visitor came from by writing the Referer URL into a cookie.
  2. The site is behind a WAF that blocks malicious strings. A WAF like Cloudflare inspects incoming requests and blocks any that contain attack signatures — an XSS or SQLi-looking string such as "><script>alert(1)</script>. When that happens, you can’t use the site until the offending input is removed.

Neither is a vulnerability by itself. The problem is what happens when the first feeds the second.

The trick

If the site writes the referrer into a cookie without sanitising it, I can poison that cookie with a WAF-triggering string — and because the cookie is then sent on every future request, the WAF blocks the user from their own account.

The mechanism, step by step:

  • An external site (exsite.com) links/redirects to the target (vulnsite.com).
  • vulnsite.com writes the referrer — the exsite.com URL — into a cookie.
  • So I build a page, exsite.com/page.html, that redirects to vulnsite.com, and I put a malicious payload in its own URL as a query string:
exsite.com/page.html?%22%3E%3Cscript%3Ealert(1)%3C%2Fscript%3E
  • When vulnsite.com loads and records the referrer, it stores that entire URL — payload and all — in the cookie. (The cookie is written after the page loads, so the first visit goes through fine.)
  • On the next request, the browser sends that poisoned cookie, the WAF sees the attack string inside it, and blocks the user. They can no longer reach the site until they manually clear the cookie — which most users have no idea how to do.

The payload never has to execute. Its mere presence in a cookie the WAF inspects is enough to lock the victim out.

The Upwork case

Upwork showed exactly this pattern. When an external site redirected to Upwork, Upwork set a referrer cookie containing the referring URL. Sending a referrer URL with malicious characters on the end:

https://attacker-page.example/page.html?%22%3E%3Cscript%3Ealert(1)%3C%2Fscript%3E

…caused Upwork to store the cookie with that payload value. On refresh, Cloudflare blocked access to Upwork — and because the cookie had a long expiry, the lockout persisted.

I reported it; Upwork patched it (details in the fix below) and rewarded a $400 bounty. I found the same issue on other sites too — some triaged and rewarded it, and at the time several remained unpatched.

dos-waf-bounty

Attack scenario

  1. The attacker builds the crafted page and hosts it anywhere.
  2. They send the crafted URL to a victim (a user of the affected site).
  3. The victim clicks it; the payload is silently written into their referrer cookie for the target site.
  4. The victim can no longer access the site — their own WAF now blocks them on every request — until they clear the cookie.

It needs no privileges and works across operating systems and browsers, because it abuses the site’s own cookie + WAF behaviour, not anything client-specific.

The fix

The root cause is storing an unsanitised, full referrer URL in a cookie. Two clean fixes:

  1. Store only the domain (www.site.com) in the referrer cookie, not the full URL with its query string — so there’s nowhere for a payload to ride along.
  2. Encode the cookie value (for example, base64) so whatever is stored can’t match a WAF attack signature.

Upwork fixed it with option 2, base64-encoding the referrer value.

Takeaways

  • Think about data the app stores about you, then sends back. Referrer cookies, user-agent logging, cached headers — anything the app records from the request and replays later is worth testing. The attack surface isn’t only what’s displayed; it’s what’s stored and re-sent.
  • A WAF can be turned against its own user. Signature-based blocking assumes the attack comes from the attacker. If you can plant the signature in something the victim sends every request (a cookie), the WAF becomes the denial-of-service tool.
  • “Harmless” behaviours combine into real bugs. Storing a referrer is fine. Running a WAF is good. Together, without sanitisation, they’re a persistent client-side DoS. Logic bugs live in these intersections — which scanners miss.
  • Think like a bad guy, and try the uncommon path. This one came from doing something deliberately weird rather than running a tool. Use your head, not just a scanner.

Thanks for reading — hope it was useful. Happy hacking!

Anas Mahmood

Web & API penetration tester and bug bounty hunter. I write up the bugs I find and the methods that found them.

Leave a Reply

Your email address will not be published. Required fields are marked *