GraphQL
Some things to consider while testing GraphQL endpoints – Introspection disabled
A. Broken Access Control (ID Enumeration)
Attack: If tasks(id: $id)
does not check ownership properly, an attacker could supply arbitrary task IDs to view other users’ tasks.
Exploit:
- Modify the
id
parameter to inject random task IDs:
json
CopyEdit
{ "id": ["123e4567-e89b-12d3-a456-426614174000"] }
- If the API does not enforce authorization, the attacker could scrape tasks from other users.
Mitigation: Ensure the API checks whether the requesting user is the owner of the tasks they query.
B. Account & Organization Data Exposure
Attack: The account
, organization
, and customer
fields leak internal IDs and names, which could be used for further enumeration or social engineering.
Exploit:
- Query an organization’s full list of users by finding tasks belonging to different accounts.
- Use
customer { id, name }
to map client-company relationships. - Use
account { id, name, kind }
to determine account types (e.g., admin vs. standard).
Mitigation: Restrict fields based on user roles to prevent mass enumeration.
C. Email Enumeration & Social Engineering
Attack: The initiatedBy
and canceledBy
fields expose full names, email addresses, and identity providers.
Exploit:
- An attacker could scrape user emails and perform phishing attacks or credential stuffing.
- If
identityProvider
includes Google, Azure AD, or Okta, the attacker knows what SSO provider is used.
Example Malicious Query:
graphql
CopyEdit
{ tasks { initiatedBy { id firstName lastName email identityProvider } } }
If this is allowed without restrictions, an attacker could dump all users’ emails and SSO providers!
Mitigation:
- Remove
email
andidentityProvider
unless explicitly needed. - Restrict GraphQL queries based on RBAC (Role-Based Access Control).
D. External URL Leakage
Attack: The result.meta.url
field might contain sensitive URLs.
Exploit:
- If these URLs link to internal admin dashboards or APIs, an attacker could try to access them directly.
- If they contain S3 bucket links or signed URLs, an attacker could download sensitive reports.
Mitigation: Ensure result.meta.url
only exposes URLs if the user has explicit permission.
E. GraphQL Query Abuse & Mass Enumeration
Attack: If there are no rate limits, an attacker could:
- Use GraphQL batching to send multiple queries in a single request.
- Run an exponential query using recursion, retrieving huge amounts of data.
Example Mass Query:
graphql
CopyEdit
{ tasks { ...Task subtasks { ...Task subtasks { ...Task } } } }
Mitigation:
- Rate limit GraphQL queries.
- Restrict deeply nested queries with max depth limits.
3. Exploit Scenarios
Scenario 1: Attacker Scrapes All User Emails
- Attacker modifies the query to return all users who started or canceled tasks.
- Attacker collects emails and SSO provider names.
- Attacker performs phishing attacks targeting identity provider (SSO) users.
Scenario 2: Attacker Enumerates Internal Accounts
- Attacker submits random account IDs in
$id
. - If access control is weak, they retrieve task data from multiple accounts.
- Attacker now knows client relationships and internal teams.
Scenario 3: Attacker Finds Internal URLs
- Attacker modifies the query to return
result.meta.url
. - The response includes internal S3 URLs or API endpoints.
- Attacker attempts to access these directly.
4. Defense Recommendations
Vulnerability | Fix |
---|---|
ID enumeration (tasks by arbitrary ID) | Enforce strict access control for task ownership. |
User email exposure | Remove email field unless explicitly needed. |
SSO provider leaks (identityProvider ) | Restrict this field to admin users only. |
Uncontrolled nested queries | Limit query depth and request size. |
No rate limits | Enforce rate limiting on GraphQL requests. |
Sensitive URLs exposed | Validate result.meta.url access permissions. |
Next Steps
- Test for authorization bypass:
- Try querying task IDs from other accounts.
- Check if you can see other users’ tasks.
- Test for email leakage:
- See if you can extract all users’ emails.
- Check for internal URLs:
- Modify the query to fetch
result.meta.url
.
- Modify the query to fetch