GraphQL Security: Attack Surface yang Sering Diabaikan Developer

Penetration-test.id
26 August 2026
GraphQL Security: Attack Surface yang Sering Diabaikan Developer

Pendahuluan

GraphQL menawarkan fleksibilitas yang tidak dimiliki REST: client bisa meminta persis data yang dibutuhkan lewat satu endpoint, satu query. Fleksibilitas ini yang membuat adopsinya terus naik, terutama di aplikasi mobile dan produk dengan kebutuhan data yang kompleks.  

Tapi fleksibilitas yang sama juga yang membuat attack surface-nya berbeda dari REST, dan sering luput dari checklist security tim development. Banyak kontrol yang biasanya otomatis di REST (rate limiting per endpoint, validasi input per route) tidak berlaku begitu saja di GraphQL, karena semua traffic lewat satu endpoint dengan struktur query yang bisa dibentuk bebas oleh client.  

Dalam engagement pengujian keamanan API, GraphQL yang diimplementasikan tanpa mempertimbangkan karakteristik ini adalah sumber temuan yang konsisten muncul. Artikel ini membahas bagaimana GraphQL bekerja, kerentanan yang paling sering ditemukan, dan bagaimana seharusnya diimplementasikan.  

Bagaimana GraphQL Bekerja

GraphQL adalah query language untuk API, biasanya diakses lewat satu endpoint HTTP (umumnya /graphql). Client mengirim query yang mendeskripsikan struktur data yang diinginkan, server merespons dengan struktur yang sama persis.  

Skema GraphQL mendefinisikan seluruh tipe data, field, dan relasi yang tersedia lewat API. Resolver adalah fungsi yang menjalankan logika untuk mengambil data tiap field. Karena satu query bisa memanggil banyak resolver sekaligus, termasuk resolver yang saling bertumpuk lewat relasi antar tipe, kompleksitas satu request bisa jauh lebih tinggi dari yang terlihat di permukaan.  

Keamanan GraphQL bergantung pada tiga lapis kontrol: skema yang tidak mengekspos lebih dari yang perlu, resolver yang memvalidasi otorisasi di setiap field, dan server yang membatasi kompleksitas query yang diizinkan masuk.  

Kerentanan yang Paling Sering Ditemukan

1. Introspection Aktif di Production

GraphQL punya fitur introspection: client bisa query skema itu sendiri untuk tahu tipe data, field, argumen, dan relasi apa saja yang tersedia. Fitur ini sangat membantu saat development, tapi kalau tetap aktif di production, attacker praktis mendapat dokumentasi lengkap API tanpa perlu reconnaissance manual.  

Dengan satu query introspection, attacker bisa memetakan seluruh skema: field mana yang menyimpan data sensitif, mutation apa saja yang tersedia, dan tipe data internal yang sebenarnya tidak dimaksudkan untuk terekspos ke client. Ini mempercepat tahap awal serangan secara signifikan, karena attacker tidak perlu menebak-nebak struktur API.  

Introspection yang aktif di production adalah temuan yang paling sering muncul dalam pengujian GraphQL, kemungkinan besar karena secara default banyak library GraphQL mengaktifkannya tanpa konfigurasi tambahan, dan tim development jarang menonaktifkannya secara eksplisit sebelum deploy.  

2. Query Depth dan Complexity Attack

Karena GraphQL mengizinkan nested query lewat relasi antar tipe, client bisa membentuk query yang bertumpuk sangat dalam, misalnya user yang punya banyak post, tiap post punya banyak comment, tiap comment punya author, dan author itu punya banyak post lagi, berulang berkali-kali.  

Query semacam ini disebut deeply nested query atau circular query. Jika server tidak membatasi kedalaman atau kompleksitas query, satu request bisa memicu ribuan hingga jutaan operasi resolver di backend, cukup untuk menghabiskan resource server dan menyebabkan denial of service, meski dikirim dari satu client saja.  

Kerentanan ini sering luput karena dari sisi request terlihat seperti query yang valid dan legal secara sintaks, bukan payload yang mencurigakan seperti pada serangan injection.  

3. Batching dan Alias-Based Abuse

GraphQL mengizinkan pengiriman banyak query atau operasi sekaligus dalam satu request lewat batching, dan mengizinkan alias untuk memanggil field atau mutation yang sama berkali-kali dalam satu query dengan nama berbeda.  

Dua fitur ini bisa dikombinasikan untuk membypass rate limiting yang hanya menghitung jumlah HTTP request. Attacker bisa mengirim ratusan percobaan login, brute force OTP, atau enumerasi data lewat alias dalam satu request saja, yang di level HTTP hanya tercatat sebagai satu kali panggilan.  

Ini jadi salah satu cara paling praktis untuk brute force credential atau enumerasi user di API GraphQL yang rate limiting-nya diimplementasikan di level request, bukan di level operasi.  

4. Broken Authorization di Level Field dan Resolver

Di REST, otorisasi biasanya dicek di level endpoint. Di GraphQL, satu query bisa menyentuh banyak tipe dan field sekaligus, sehingga otorisasi harus dicek di level resolver masing-masing field, bukan cuma di level query secara keseluruhan.  

Kesalahan yang sering ditemukan: tim development mengecek otorisasi di resolver top-level (misalnya query getUser), tapi lupa mengecek ulang otorisasi di resolver nested yang dipanggil dari relasi (misalnya field salary di dalam tipe Employee yang diakses lewat relasi dari tipe lain). Akibatnya, attacker bisa mengakses data yang seharusnya terproteksi lewat jalur query yang tidak terduga, meski jalur query utamanya sudah diproteksi dengan benar.  

Pola ini adalah bentuk broken object/field level authorization yang spesifik untuk GraphQL, dan sering tidak terdeteksi kalau pengujian hanya menyasar query yang "wajar" tanpa mengeksplorasi kombinasi relasi yang tersedia di skema.  

5. Excessive Data Exposure lewat Over-fetching

Karena client menentukan sendiri field apa yang diminta, resolver di backend sering ditulis untuk mengembalikan seluruh objek dari database, lalu mengandalkan skema GraphQL untuk memfilter field mana yang ditampilkan ke client.  

Masalahnya, kalau resolver mengembalikan objek penuh ke resolver layer, ada risiko field sensitif ikut terekspos, baik lewat kesalahan konfigurasi skema, lewat introspection yang menunjukkan keberadaan field tersebut, maupun lewat query yang mengeksploitasi field yang lupa di-restrict.  

Dalam pengujian, hal ini sering ditemukan dalam bentuk field seperti password hash, token internal, atau data pengguna lain yang ternyata bisa diminta lewat query yang sedikit dimodifikasi dari query normal aplikasi.  

Implementasi yang Benar

Nonaktifkan Introspection di Production

Introspection sebaiknya hanya aktif di environment development. Sebagian besar library GraphQL modern menyediakan opsi untuk menonaktifkannya lewat konfigurasi, dan ini harus jadi bagian dari checklist sebelum deploy ke production.  

Batasi Depth dan Complexity Query

Server harus membatasi kedalaman maksimum query yang diizinkan dan menghitung skor kompleksitas tiap query sebelum dieksekusi. Query yang melebihi batas depth atau complexity score ditolak sebelum resolver dijalankan, bukan setelah resource sudah terpakai.  

Terapkan Rate Limiting di Level Operasi, Bukan Request

Rate limiting harus menghitung jumlah operasi dan cost tiap query, bukan hanya jumlah HTTP request. Ini mencegah batching dan alias digunakan untuk membypass limit yang dihitung secara naif di level request.  

Validasi Otorisasi di Setiap Resolver

Setiap resolver yang mengembalikan data harus melakukan pengecekan otorisasi sendiri, tidak mengandalkan pengecekan di resolver top-level. Ini terutama penting untuk field dan tipe yang bisa diakses lewat lebih dari satu jalur relasi di skema.  

Terapkan Query Whitelisting atau Persisted Queries untuk Production

Untuk aplikasi dengan client yang dikontrol sendiri (misalnya aplikasi mobile resmi), persisted queries membatasi server untuk hanya menerima query yang sudah terdaftar sebelumnya, bukan query bebas dari client. Ini menutup banyak vektor serangan sekaligus, termasuk deeply nested query dan eksplorasi skema lewat kombinasi field yang tidak terduga.  

Kesimpulan

GraphQL bukan lebih tidak aman dari REST, tapi model keamanannya berbeda, dan kontrol yang biasa diandalkan di REST tidak otomatis berlaku di GraphQL. Kerentanan yang muncul kebanyakan bukan soal bug di library, melainkan asumsi keliru bahwa fleksibilitas skema tidak perlu diimbangi dengan kontrol tambahan di level query dan resolver.  

Pengujian keamanan API berbasis GraphQL perlu mencakup lebih dari sekadar memeriksa satu-dua endpoint, tapi juga mengeksplorasi kombinasi relasi di skema, batasan kompleksitas query, dan otorisasi di level field.  

Jika Anda ingin memastikan implementasi GraphQL API Anda sudah benar dan aman, tim Security Squad LOGIQUE siap membantu.

Yuan Edric Iskandar

Yuan Edric Iskandar

adalah penetration tester di LOGIQUE Security Squad dengan spesialisasi di application security, khususnya Android dan iOS. Ia memegang sertifikasi CEH Master dan memiliki pengalaman langsung dalam pengujian keamanan aplikasi mobile di berbagai industri, termasuk fintech dan manufaktur. Selain praktik pengujian, ia aktif mengembangkan tools internal untuk static analysis dan security testing pada platform Android.

Lindungi Sebelum Diserang

Sistem Anda Rentan terhadap Attack Serupa?

LOGIQUE Security Squad membantu Anda menemukan celah sebelum penyerang menemukannya lebih dulu.

Artikel Terkait