Created
September 26, 2024 15:52
-
-
Save BuffaloWill/a50c7fe465b98884ed42e1a94aaea56c to your computer and use it in GitHub Desktop.
Revisions
-
BuffaloWill created this gist
Sep 26, 2024 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,102 @@ ## Summary This document has references and notes from the OWASP Global AppSec 2024 talk; "GraphQL Exploitation: Secondary Context Attacks and Business Logic Vulnerabilities". ## Author * Github: [BuffaloWill](https://github.com/BuffaloWill) * LinkedIn: [Will Vandevanter](https://www.linkedin.com/in/willis-vandevanter-82a05018/) ## ### Secondary Context Attacks References * Hacking Starbucks and Accessing Nearly 100 Million Customer Records - Sam Curry 06/20/2020 * [https://samcurry.net/hacking-starbucks](https://samcurry.net/hacking-starbucks) * Leaked Secrets and Unlimited Miles: Hacking the Largest Airline and Hotel Rewards Platform - Sam Curry 08/03/2023 * [https://samcurry.net/points-com](https://samcurry.net/points-com) * KernelCon 2020: Attacking Secondary Contexts in Web Applications - Sam Curry * [https://www.youtube.com/watch?v=hWmXEAi9z5w](https://www.youtube.com/watch?v=hWmXEAi9z5w) ### Tool References * [https://github.com/BuffaloWill/burpsuite-project-file-parser](https://github.com/BuffaloWill/burpsuite-project-file-parser) ### Defense References * [GraphQL Scalars - https://the-guild.dev/graphql/scalars/docs](https://the-guild.dev/graphql/scalars/docs) * [Escape Tech - How To Secure GraphQL APIs](https://escape.tech/blog/how-to-secure-graphql-apis/) ### Bambadas Code GraphQL Operation Name in URL ``` return requestResponse.request().parameterValue("operationName", HttpParameterType.URL); ``` Show Content Type in Table Column: ``` return requestResponse.request().headerValue("Content-Type"); ``` Highlight a request if it has ID! in it. This gets kind of janky trying to pull the mutation or query name: ``` // Get the request body String body = requestResponse.request().bodyToString(); if (body.contains("ID!") || body.contains("String!")) { requestResponse.annotations().setHighlightColor(HighlightColor.RED); } // Check for POST requests (most common for GraphQL) if (requestResponse.request().method().equals("POST")) { try { // Pattern to match mutations, including inline definitions and input parameters Pattern mutationPattern = Pattern.compile("\"mutation\"\\s*:\\s*\"\\s*(mutation\\s+(\\w+)(\\([^)]*\\))?|mutation)\\s*\\{|\"mutation\"\\s*:\\s*\"mutation\\s+(\\w+)(\\([^)]*\\))?"); Matcher mutationMatcher = mutationPattern.matcher(body); if (mutationMatcher.find()) { String operationName = mutationMatcher.group(2) != null ? mutationMatcher.group(2) : mutationMatcher.group(4); String inputs = mutationMatcher.group(3) != null ? mutationMatcher.group(3) : (mutationMatcher.group(5) != null ? mutationMatcher.group(5) : ""); if (operationName != null && !operationName.isEmpty()) { return "mutation " + operationName + inputs; } else { return "mutation (unnamed)" + inputs; } } // If no mutation found, check for queries Pattern queryPattern = Pattern.compile("\"query\"\\s*:\\s*\"\\s*(query\\s+(\\w+)(\\([^)]*\\))?|query)\\s*\\{|\"query\"\\s*:\\s*\"query\\s+(\\w+)(\\([^)]*\\))?"); Matcher queryMatcher = queryPattern.matcher(body); if (queryMatcher.find()) { String operationName = queryMatcher.group(2) != null ? queryMatcher.group(2) : queryMatcher.group(4); String inputs = queryMatcher.group(3) != null ? queryMatcher.group(3) : (queryMatcher.group(5) != null ? queryMatcher.group(5) : ""); if (operationName != null && !operationName.isEmpty()) { return "query " + operationName + inputs; } else { return "query (unnamed)" + inputs; } } } catch (Exception e) { // If parsing fails, try to find GraphQL operations in raw body Pattern rawPattern = Pattern.compile("(mutation|query)\\s+(\\w+)(\\([^)]*\\))?"); Matcher rawMatcher = rawPattern.matcher(body); if (rawMatcher.find()) { String inputs = rawMatcher.group(3) != null ? rawMatcher.group(3) : ""; return rawMatcher.group(1) + " " + rawMatcher.group(2) + inputs; } else { // Check for unnamed operations Pattern unnamedPattern = Pattern.compile("(mutation|query)\\s*(\\([^)]*\\))?\\s*\\{"); Matcher unnamedMatcher = unnamedPattern.matcher(body); if (unnamedMatcher.find()) { String inputs = unnamedMatcher.group(2) != null ? unnamedMatcher.group(2) : ""; return unnamedMatcher.group(1) + " (unnamed)" + inputs; } } } } ```