# CSRF protection bypass on any Django powered site via Google Analytics

Google Analytics __utmz cookie reflects unfiltered Referer path; Django's cookie parser treats ] as delimiter, letting an attacker inject a csrftoken cookie and bypass CSRF protection.

- Payout: hidden
- Severity: high
- Program: Django
- Found by: bobrov
- Disclosed: 2016-09-26
- Write-up quality: 9/10
- Original: https://hackerone.com/reports/26647
- Library page: https://bugbountylibrary.com/r/h1%3A26647
- Tags: area:web domain:web impact:integrity kind:bounty platform:hackerone sev:high tech:python technique:chained technique:parser-differential vuln:csrf

**Target:** Django cookie parser / CSRF middleware
**Root cause:** Python http.cookies SimpleCookie regex treats [ \ ] as cookie delimiters, so a crafted __utmz value containing ']csrftoken=x' is parsed as a separate csrftoken cookie. Google Analytics writes attacker-controlled Referer path into __utmz unfiltered.
**Steps:**
1. Victim authenticates on target Django site using cookie-based CSRF protection.
2. Attacker page loads an iframe pointing to a URL whose path contains `,]csrftoken=x,;domain=.instagram.com;path=/;...` and Referer set to a blog.instagram.com URL.
3. Google Analytics sets `__utmz=90378079.1401435337.1.1.utmcsr=blackfan.ru|utmccn=(referral)|utmcmd=referral|utmcct=/r/,]csrftoken=x,` for .instagram.com.
4. Django parses `__utmz` and, due to `]` delimiter, extracts `csrftoken=x`.
5. Attacker auto-submits a POST form with `csrfmiddlewaretoken=x` to the target endpoint, passing CSRF validation.
**How found:** Researcher noticed Google Analytics stores the Referer path in __utmz unfiltered, then tested how Python's SimpleCookie parses delimiters and found `]` splits cookies, and combined with browser cookie-attribute quirks to scope the injected cookie.
**Exploitation:** Attacker hosts a page with an iframe to a Google Analytics-enabled subdomain URL crafted so the Referer path injects `]csrftoken=x,` into __utmz; Chrome domain-attribute trick rewrites the cookie to `.site.com`. Then a hidden form POSTs to the victim action with csrfmiddlewaretoken=x, performing state-changing requests as the victim (e.g. Instagram follow).
**Escalation:** Chrome's limited cookie-attribute handling allows overriding the domain attribute via repeated `domain=` params to scope the injected cookie to the parent domain, enabling cross-subdomain exploitation.
**Insight:** Look for cookies whose values reflect attacker-controlled input (Referer, URL path) and cross-reference with the target framework's cookie parser delimiter set — mismatches between browser and server cookie parsing enable cookie injection and CSRF token fixation.

## Proof of concept (copied exactly from the original report)

**Cookie injection URL setting csrftoken via __utmz**

```
http://blackfan.ru/r/,]csrftoken=x,;domain=.instagram.com;path=/;path=/;path=/;path=/;path=/;path=/;path=/;path=/;path=/;path=/;path=/;path=/;path=/;path=/;path=/;path=/;?r=http://blog.instagram.com/
```

**Python SimpleCookie parsing delimiter bypass demo**

```
>>> from http import cookies
>>> C = cookies.SimpleCookie()
>>> C.load('__utmz=blah]csrftoken=x')
>>> C
<SimpleCookie: csrftoken='x'>
```

