GraphQL & Modern API Attacks
Attack techniques specific to GraphQL and modern API architectures: introspection abuse, nested query attacks, batching exploits, and alias abuse
By Benjamin, Fraud Attacks · Updated
GraphQL is an API query language that lets clients describe exactly which data they want in a single request instead of calling many fixed REST endpoints. That flexibility creates attack surfaces REST doesn't have: introspection reveals the whole schema, nested queries traverse relationships exponentially, and aliases or batches let attackers repeat operations inside one HTTP request to slip past rate limits. This article covers each attack and the defenses that constrain them.
The Query That Pulled Everything
Sophia Kim was a security engineer at a fintech startup that had migrated its API from REST to GraphQL six months earlier. The developers loved it. Frontend teams could request exactly the data they needed in a single query. No more chaining multiple API calls together.
On a Tuesday afternoon, Sophia's monitoring flagged an anomaly. A single API request had returned 47 megabytes of data. The average response was 2 kilobytes.
She pulled the query. It was a single GraphQL request, beautifully crafted:
query {
user(id: "12345") {
accounts {
transactions(last: 1000) {
amount
recipient {
accounts {
transactions(last: 1000) {
amount
recipient {
name
email
accounts {
balance
}
}
}
}
}
}
}
}
}
Starting from one user, the query walked relationships: user to accounts, accounts to transactions, transactions to recipients, recipients to their accounts, those accounts to their transactions, and so on. Each level multiplied the data returned. The query was technically valid. Every field existed in the schema. But the combinatorial data retrieval had effectively let one authenticated user extract financial data for thousands of other customers.
The query had been submitted by a legitimate user account. No credentials were stolen. No authentication was bypassed. The API did exactly what it was asked to do. The problem was that it shouldn't have been possible to ask.
This story is fictional, but the patterns are real.
Why This Matters
In previous API articles, you learned about general API security concepts and business logic attacks. This article focuses on attacks specific to modern API architectures, particularly GraphQL, which has become the standard for many fintech, e-commerce, and SaaS applications.
GraphQL's popularity comes from its flexibility. Clients can ask for exactly the data they need, reducing over-fetching (getting too much data) and under-fetching (needing multiple requests). But that same flexibility creates attack surfaces that don't exist in traditional REST APIs.
Understanding these attacks matters for fraud analysts because many of the platforms you work with, payment processors, banking APIs, marketplace backends, have adopted GraphQL or similar modern API patterns. The attacks described here can be used for data theft, account enumeration, and fraud at scale.
GraphQL: A Quick Primer
If you haven't encountered GraphQL before, here's the essential context.
Traditional REST APIs have fixed endpoints. You call /api/users/123 to get user data, /api/users/123/transactions to get their transactions, and /api/users/123/accounts to get their accounts. The server decides what data each endpoint returns.
GraphQL takes a different approach. There's usually a single endpoint (/graphql), and the client sends a query describing exactly what data it wants. The server returns only what was asked for, nothing more.
This is powerful for legitimate use. A mobile app that only needs a user's name and balance doesn't need to download their full profile, transaction history, and preferences. It can ask for just two fields.
But this flexibility means the client has more control over what the server does. And more client control means more opportunities for abuse.
For hands-on practice exploiting GraphQL APIs, PortSwigger's Web Security Academy GraphQL track↗[2] offers free labs covering introspection, batching, and alias-based attacks.
Introspection Abuse: Reading the Blueprint
What Is Introspection?
GraphQL has a built-in feature called introspection↗[1] that lets clients ask the API to describe itself. An introspection query returns the complete schema: every type, every field, every relationship, every argument the API accepts.
For developers building applications against the API, introspection saves real time. It powers autocomplete in development tools and helps teams understand the API's capabilities.
For attackers, introspection is a detailed map of the attack surface.
The Reconnaissance Value
When an attacker runs an introspection query against a GraphQL API, they learn:
- Every data type the API exposes (User, Account, Transaction, InternalNote, AdminAction)
- Every field within each type (socialSecurityNumber, internalFraudScore, accountBalance)
- Every relationship between types (which lets them craft nested queries like Sophia discovered)
- Every mutation (write operation) the API supports (transferFunds, changePassword, grantAdminAccess)
- Every argument each query or mutation accepts (including filters, limits, and parameters)
This is equivalent to giving a burglar the floor plans, the alarm system layout, and a list of everything valuable in the building. An attacker with the schema can identify sensitive fields that might not be properly protected, find admin-only operations that might have authorization flaws, understand the data model well enough to craft precise extraction queries, and discover hidden or deprecated functionality that might be less protected.
The Defense Gap
Many production GraphQL APIs still have introspection enabled. During development, it's essential. But in production, leaving introspection on gives every anonymous user (including attackers) the complete API blueprint.
Disabling introspection in production is the first recommendation in most GraphQL security guides. But even with introspection disabled, determined attackers can reverse-engineer the schema by sending queries and observing error messages (which often reveal field names and types), analyzing client-side code that constructs GraphQL queries, and using wordlist-based schema guessing tools.
Disabling introspection raises the bar. It doesn't eliminate the risk.
Nested Query Attacks: Death by Depth
The Combinatorial Problem
Sophia's case illustrates the most distinctive GraphQL vulnerability: nested query abuse. Because GraphQL relationships can be traversed in queries, an attacker can construct queries that explode combinatorially as they traverse deeper relationships. With roughly constant fan-out per level, result-set size grows exponentially in the depth of the query. Each additional level multiplies by the average fan-out, as the worked example below makes concrete. The point is that small queries can produce enormous responses.
Consider a social network API. A user has friends. Each friend has friends. Each of those friends has friends. A query three levels deep starting from one user with 100 friends would try to return: level 1 (100 friends) + level 2 (100 x 100 = 10,000) + level 3 (100 x 100 x 100 = 1,000,000). That's over a million records from a single query.
In financial applications, these relationships might be: user to accounts, accounts to transactions, transactions to counterparties, counterparties to their accounts and transactions. The data returned at each level multiplies.
Resource Exhaustion
Deep nested queries don't just return too much data. They can crash the server.
Each level of nesting generates database queries. A 5-level nested query might trigger thousands or millions of database operations. The database bogs down. Response times spike. Other users' requests start failing. A single malicious query can effectively become a denial of service attack. This is the GraphQL-specific manifestation of API4:2023, Unrestricted Resource Consumption[3] in the OWASP API Security Top 10.
This is particularly dangerous because it looks like a legitimate API call. There's no brute force, no credential stuffing, no volume of requests. Just one carefully crafted query that consumes disproportionate server resources.
Query Complexity Limits
The primary defense against nested query attacks is query complexity analysis. Before executing a query, the server calculates a "cost" based on:
- Depth: How many levels of nesting the query contains
- Breadth: How many fields are requested at each level
- Estimated result size: Based on known cardinalities (a user might have 5 accounts, each with 500 transactions)
If the calculated cost exceeds a threshold, the query is rejected before execution. The server returns an error like "Query complexity exceeds maximum allowed" without doing any actual database work.
Effective complexity limits require understanding your data model. A blanket "max depth of 3" might be too restrictive for legitimate use cases while still allowing expensive queries at shallow depths. Thoughtful cost analysis based on actual data relationships works better.
Batching Attacks: Volume Through Consolidation
How Batching Works
Many GraphQL implementations support query batching: sending multiple queries in a single HTTP request. Instead of making 100 separate API calls, a client can send all 100 queries in one request.
For legitimate use, batching improves performance. A mobile app loading a dashboard can batch queries for the user's profile, recent transactions, notifications, and account balances into one round trip instead of four.
Batching for Brute Force
Attackers use batching to circumvent rate limits. If a rate limit is "10 login attempts per minute per IP address," and the attacker sends a batch of 100 login mutations in a single request, does that count as 1 request or 100?
Many rate limiting implementations count HTTP requests, not the operations within them. A batch of 1,000 password guesses arrives as a single HTTP request and passes through rate limits designed to count requests, not operations.
This makes batching particularly dangerous for:
Account enumeration. Batch queries like "does user_a@email.com exist? does user_b@email.com exist? does user_c@email.com exist?" can check thousands of email addresses in a single request.
Credential testing. Batch mutations that attempt login with different password combinations, bypassing per-request rate limits.
OTP brute forcing. If a one-time password is 6 digits (1 million combinations), a batched attack could try all combinations in 1,000 requests of 1,000 attempts each.
Defending Against Batch Abuse
Effective defenses include:
- Operation-level rate limiting. Count individual operations within a batch, not just HTTP requests.
- Batch size limits. Cap the number of queries allowed in a single batch (10-50 is common).
- Mutation batching restrictions. Disallow batching for sensitive operations (login, password reset, fund transfers) entirely.
- Cost-based throttling. Apply the same query complexity analysis to each operation in a batch, with a total cost budget per request.
Alias-Based Attacks
Aliases in GraphQL
GraphQL aliases let a client rename fields in the response. This is legitimately useful when a query requests the same field multiple times with different arguments:
query {
checking: account(type: "checking") { balance }
savings: account(type: "savings") { balance }
}
The aliases "checking" and "savings" prevent field name collisions in the response.
Aliases as a Batching Workaround
Even when batching is disabled, aliases allow a similar effect within a single query. An attacker can use aliases to repeat the same operation hundreds of times:
query {
a1: login(email: "victim@email.com", password: "password1") { token }
a2: login(email: "victim@email.com", password: "password2") { token }
a3: login(email: "victim@email.com", password: "password3") { token }
# ... hundreds more
}
Each alias triggers a separate execution of the login resolver. If rate limiting only counts queries (not alias repetitions), this bypasses the intended protection. This is the GraphQL form of API2:2023, Broken Authentication[4]: the verification function is fine, but the surrounding controls let attackers call it too many times.
Defending against alias abuse requires counting resolver executions, not just queries or HTTP requests. The server should track how many times each resolver is called regardless of whether those calls came from batched queries, aliases within a single query, or individual requests.
Modern API Patterns and Fraud
Why This Matters for Fraud Teams
You might be wondering how these technical API attacks connect to fraud investigation. The connection is direct:
Data theft enables fraud. Sophia's nested query extracted financial data for thousands of customers. That data (names, email addresses, account balances, transaction patterns) is exactly what criminals need for targeted phishing, account takeover, and social engineering.
Account enumeration enables credential stuffing. If an attacker can confirm which email addresses have accounts at your institution, they can focus credential stuffing attacks on verified accounts rather than spraying at random.
Rate limit bypass enables brute force. OTP brute forcing through batch attacks can bypass two-factor authentication. Password spraying through alias attacks can compromise accounts that reuse common passwords.
API abuse enables automation. Every attack described here can be automated and run at scale. A single attacker with the right queries can extract more data, test more credentials, and enumerate more accounts than a team of humans.
What Fraud Analysts Should Watch For
When investigating potential API abuse, these signals stand out:
- Unusually large API responses (like the 47 MB response Sophia flagged)
- Single users or IP addresses generating disproportionate database load
- Login failures that arrive in bursts rather than individually
- Queries for fields that normal application flows don't access (like internal fraud scores or admin fields)
- Patterns of data access that walk relationship trees (user to transactions to counterparties to their transactions)
You don't need to read GraphQL queries to investigate API abuse. You need to understand the patterns that indicate someone is using the API in ways it wasn't intended to be used. Machine-learning anomaly detection on API logs tends to surface these patterns more reliably than rule-based monitoring, because the abusive shape of a query (size, depth, repetition) is structural rather than rule-violating.
Key Takeaways
- GraphQL's flexibility is also its vulnerability. The ability for clients to specify exactly what data they want means attackers can craft queries that extract far more than intended.
- Introspection is a reconnaissance goldmine. A single query can reveal the complete API schema, giving attackers a detailed map of every data type, relationship, and operation available.
- Nested queries can cause combinatorial data extraction. Traversing relationships in a GraphQL query multiplies the data returned at each level, enabling mass data theft through a single technically valid request.
- Batching and aliases bypass request-level rate limits. Defenses must count operations, not HTTP requests, to be effective against these techniques.
- API architecture choices have direct fraud implications. Data theft, account enumeration, and authentication bypass through API attacks feed directly into fraud operations.
What's next: With an understanding of both traditional and modern API attacks, you can apply these concepts when investigating suspicious activity that originates from programmatic access rather than human browsing. The API Investigation article covers how fraud analysts reconstruct what happened during an API-based attack.
References
1. graphql.org — Introspection↗ - Official documentation of GraphQL's schema-introspection feature.
2. PortSwigger Web Security Academy — GraphQL API vulnerabilities↗ - Free interactive labs covering introspection, batching, and alias attacks.
3. OWASP API4:2023 — Unrestricted Resource Consumption↗ - The 2023 API Top 10 entry covering missing limits on query complexity, request size, and compute cost.
4. OWASP API2:2023 — Broken Authentication↗ - Covers credential testing, brute force, and weak login-flow protections.
Key Terms
| Term | Definition |
|---|---|
| GraphQL | A query language for APIs where clients specify exactly what data they want, using a single endpoint with flexible queries |
| Introspection | GraphQL's built-in feature that allows clients to query the API's schema, revealing all available types, fields, and operations |
| Nested query attack | Crafting a GraphQL query that traverses relationships to exponentially expand the data returned |
| Query complexity analysis | Server-side calculation of a query's expected cost (depth, breadth, estimated results) to reject expensive queries before execution |
| Batching | Sending multiple GraphQL operations in a single HTTP request |
| Alias | A GraphQL feature that lets clients rename fields, which can be abused to repeat operations within a single query |
| Account enumeration | Systematically testing which identifiers (emails, usernames) have active accounts on a platform |
| Resolver | The server-side function that handles fetching data for a specific GraphQL field |
Test Your Knowledge
Ready to test what you've learned? Take the quiz to reinforce your understanding.
Continue learning
- API Abuse & Business LogicAPI & Business Logic 101What APIs are and why they matter for fraud, explained for analysts with no technical background
- API Abuse & Business LogicBusiness Logic AttacksHow criminals exploit mathematical errors, workflow flaws, and authorization gaps
- API Abuse & Business LogicWebhook & API SecurityHow criminals exploit webhooks, leaked API keys, and rate limiting gaps to forge notifications, steal data, and bypass authentication
- More from Fraud BasicsFraud 101: What Is Fraud?Absolute basics for someone who has never looked at fraud: what is fraud, how is it different from other crimes, and why does it matter
- More from Money Movement & Transaction FraudPayment Systems 101: How Money Really MovesEssential foundation for understanding how ACH, wire transfers, card payments, and digital payments actually work - and why criminals target them
- More from Account TakeoverATO FundamentalsEssential foundation every fraud professional needs to know about account takeover attacks