-
Notifications
You must be signed in to change notification settings - Fork 2
GraphQL Security Testing
Hadrian provides 13 built-in GraphQL security templates covering introspection disclosure, denial-of-service attacks, authorization bypass, injection, and data exposure vulnerabilities.
# Basic GraphQL security scan (uses introspection to discover schema)
hadrian test graphql --target https://api.example.com --template-dir templates/graphql
# With SDL schema file (when introspection is disabled)
hadrian test graphql --target https://api.example.com --schema schema.graphql --template-dir templates/graphql
# With authentication for authorization testing
hadrian test graphql --target https://api.example.com --auth auth.yaml --roles roles.yaml --template-dir templates/graphqlhadrian test graphql [flags]
Flags:
--target string Target base URL (required)
--endpoint string GraphQL endpoint path (default "/graphql")
--schema string GraphQL SDL schema file (optional — uses introspection if not provided)
--roles string Roles and permissions YAML file
--auth string Authentication configuration YAML file
--template-dir string GraphQL templates directory
--depth-limit int Maximum query depth for DoS testing (default 10)
--complexity-limit int Maximum complexity for DoS testing (default 1000)
--batch-size int Queries in batch attack tests (default 100)
--proxy string HTTP/HTTPS proxy URL
--insecure Skip TLS verification
--rate-limit float Requests per second (default 5.0)
--timeout int Request timeout in seconds (default 30)
--output string Output format: terminal, json, markdown (default "terminal")
--output-file string Output file path
--verbose Verbose output
--dry-run Show what would be tested without executing
| Template | OWASP Category | Vulnerability | Severity |
|---|---|---|---|
introspection-disclosure |
API8:2023 | Introspection enabled in production | MEDIUM |
depth-attack |
API4:2023 | Missing query depth limits | HIGH |
batching-attack |
API4:2023 | Missing batch query limits | MEDIUM |
alias-dos-attack |
API4:2023 | Alias-based denial of service | HIGH |
field-duplication-attack |
API4:2023 | Field duplication DoS | MEDIUM |
circular-fragment-attack |
API4:2023 | Circular fragment DoS | HIGH |
directive-overloading |
API4:2023 | Directive abuse | MEDIUM |
bola-user-access |
API1:2023 | Broken object-level authorization | HIGH |
bfla-mutation |
API5:2023 | Broken function-level authorization | HIGH |
injection-via-variables |
API8:2023 | GraphQL injection | HIGH |
error-disclosure |
API8:2023 | Verbose error messages | MEDIUM |
excessive-data-exposure |
API3:2023 | Over-fetching sensitive data | HIGH |
Introspection Disclosure — Detects if GraphQL introspection is enabled in production, allowing attackers to discover the entire API schema.
Query Depth/Batching/Alias Attacks — Tests for missing rate limits and complexity controls that could enable resource exhaustion denial-of-service attacks.
BOLA (API1:2023) — Tests if users can access other users' data through object ID manipulation in GraphQL queries.
BFLA (API5:2023) — Tests if low-privileged users can execute admin-only mutations.
Injection via Variables — Tests for GraphQL injection through query variables.
Error Disclosure — Detects verbose error messages that leak internal implementation details.
Excessive Data Exposure — Tests if queries return more data fields than the user should have access to.
BOLA and BFLA tests require authentication configuration. See Configuration for all auth methods.
# auth.yaml
roles:
admin:
type: bearer
token: "admin-jwt-token..."
user:
type: bearer
token: "user-jwt-token..."
attacker:
type: bearer
token: "attacker-jwt-token..."# roles.yaml
roles:
- name: admin
permissions:
- "read:*:all"
- "write:*:all"
- "delete:*:all"
- name: user
permissions:
- "read:user:own"
- "write:user:own"
- name: attacker
permissions:
- "read:user:own"id: graphql-custom-check
info:
name: "Custom GraphQL Check"
category: "API3:2023"
severity: "HIGH"
test_pattern: "simple"
endpoint_selector:
requires_auth: true
role_selector:
attacker_permission_level: "lower"
victim_permission_level: "higher"
graphql:
- query: |
query {
sensitiveData {
secret
}
}
auth: "attacker"
matchers:
- type: status
status: [200]
- type: word
words: ["secret"]
part: body
detection:
success_indicators:
- type: status_code
status_code: 200
- type: body_field
body_field: "data.sensitiveData"
exists: trueSee the Template System guide for the full template format.
DVGA (Damn Vulnerable GraphQL Application) is an intentionally vulnerable GraphQL app for testing.
git clone https://github.com/dolevf/Damn-Vulnerable-GraphQL-Application.git
cd Damn-Vulnerable-GraphQL-Application
docker-compose up -d
# DVGA runs at http://localhost:5013/graphqlhadrian test graphql --target http://localhost:5013 --verbose
# Expected findings:
# [MEDIUM] introspection-disclosure: GraphQL introspection is enabled
# [HIGH] depth-attack: Server allows deeply nested queries (depth 10)
# [MEDIUM] batching-attack: Server allows batched queries (100 operations)For the complete tutorial, see Tutorials — DVGA.
Provide a schema file when introspection is disabled:
hadrian test graphql --target https://api.example.com --schema schema.graphqlFor self-signed certificates or proxy interception:
hadrian test graphql --target https://api.example.com --insecure
# Or with a CA certificate
hadrian test graphql --target https://api.example.com --ca-cert ca.crt-
Start with
--dry-runto preview what will be tested - Use appropriate rate limits — don't overwhelm the target server
- Test in staging first — never test production without explicit authorization
- Provide auth for BOLA/BFLA — authorization tests require valid tokens for multiple roles
-
Enable LLM triage with
requires_llm_triage: truefor better finding context