Introspection GraphQL publik: mengapa ini masalah dan cara mematikannya
Introspection GraphQL adalah query bawaan yang mengembalikan skema lengkap API Anda: setiap type, field, argumen, dan mutation. Fitur ini penting saat development, tetapi tidak boleh dapat dijangkau di production untuk API privat. Jika dibiarkan aktif, ini adalah peta seluruh permukaan serangan backend Anda.
Apa itu
Setiap server GraphQL mengimplementasikan sekumpulan kecil meta-field, terutama __schema dan __type. Satu POST ke /graphql dengan `query { __schema { types { name fields { name } } } }` mengembalikan definisi type lengkap.
Tool seperti GraphiQL, Apollo Sandbox, dan UI Playground bergantung pada introspection untuk melengkapi query secara otomatis dan menampilkan penjelajah skema. Saat development itulah yang Anda inginkan; di production, pada API privat, artinya siapa pun di dunia dapat mengunduh peta yang sama.
Kenapa penting
Skema menyebutkan nama model, relasi, dan setiap mutation yang Anda ekspos — termasuk field admin, internal, dan deprecated yang tidak pernah dimaksudkan untuk ditemukan dari luar. Penyerang menggunakannya untuk menyusun daftar operasi terarah untuk diuji terhadap bypass autentikasi, IDOR, dan bug injection.
Bahkan jika setiap field sudah diotorisasi dengan benar, mutation tersembunyi seperti refundOrder, impersonateUser, atau exportBackup tidak seharusnya mengiklankan dirinya. Introspection mengubah fase pengintaian penyerang dari berjam-jam menebak menjadi satu request.
Cara memperbaiki
Matikan introspection ketika NODE_ENV bernilai production. Biarkan aktif secara lokal agar tim Anda tetap bisa menjelajahi skema di Sandbox.
import { ApolloServer } from "@apollo/server";
const server = new ApolloServer({
typeDefs,
resolvers,
introspection: process.env.NODE_ENV !== "production",
});Yoga memiliki plugin resmi; graphql-http menggunakan validation rule dari graphql-js. Keduanya menghentikan query introspection sebelum dijalankan.
// GraphQL Yoga
import { createYoga } from "graphql-yoga";
import { useDisableIntrospection } from "@graphql-yoga/plugin-disable-introspection";
export const yoga = createYoga({
schema,
plugins: process.env.NODE_ENV === "production" ? [useDisableIntrospection()] : [],
});
// graphql-http (or express-graphql)
import { NoSchemaIntrospectionCustomRule } from "graphql";
const validationRules = process.env.NODE_ENV === "production"
? [NoSchemaIntrospectionCustomRule]
: [];GraphiQL, Playground, dan Apollo Sandbox dibuat untuk membantu manusia menjelajahi skema — tempatnya bukan di endpoint production publik. Lindungi dengan pemeriksaan autentikasi atau jangan pasang sama sekali di build production.
Menonaktifkan introspection adalah langkah hardening, bukan kontrol akses. Setiap field tetap membutuhkan otorisasi yang tepat di level resolver — jika tidak, siapa pun yang menebak nama field tetap bisa memanggilnya. Perlakukan introspection sebagai salah satu lapisan, bukan satu-satunya lapisan.
FAQ
Bukankah menyembunyikan skema hanya security through obscurity?
Sebagian, ya — penyerang yang gigih tetap bisa melakukan brute-force pada nama field. Tetapi membuat pengintaian menjadi murah dan lengkap layak dicegah. Setiap panduan API GraphQL komersial dan cheat sheet GraphQL OWASP merekomendasikan untuk menonaktifkan introspection di production.
Bagaimana dengan API publik di mana saya ingin developer menjelajahi skemanya?
Sajikan skema secara sengaja — publikasikan file Schema Definition Language, host situs dokumentasi, atau buka introspection hanya setelah autentikasi. Itu sangat berbeda dengan POST anonim yang mengembalikan segalanya.
Bagaimana AppSafe mendeteksinya?
AppSafe mengirim POST berisi query introspection kecil ke /graphql dan /api/graphql dan mencari respons __schema dengan status 200. Jika respons itu kembali, temuan ditandai dengan tingkat keparahan sedang di kategori Keamanan API.
Apakah aplikasimu terpengaruh?
AppSafe memeriksa ini dan puluhan masalah lain dalam satu pemindaian gratis.
Pindai aplikasiku gratisPanduan terkait
Kesalahan konfigurasi CORS: jebakan wildcard dan reflection
Izinkan setiap origin dan situs mana pun bisa membaca API-mu.
Halaman error verbose dan stack trace di production
Stack trace memberi tahu penyerang persis ke mana harus membidik.
Metode HTTP berbahaya: bagaimana TRACE, PUT, dan DELETE diiklankan
Respons OPTIONS yang mendaftar TRACE atau DELETE mengungkapkan lebih dari yang seharusnya.
API key terekspos di JavaScript sisi klien
Apa pun di bundle-mu bersifat publik. Perlakukan seperti itu.