mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-06-11 21:54:56 +03:00
4.9 KiB
4.9 KiB
API Reference — Performing GraphQL Introspection Attack
Libraries Used
| Library | Purpose |
|---|---|
requests |
Send GraphQL introspection queries and depth test payloads |
json |
Parse schema responses and format results |
argparse |
CLI argument parsing for URL, auth headers, depth limits |
Installation
pip install requests
CLI Interface
python agent.py introspect --url <graphql_endpoint> [--auth-header "Bearer token"]
python agent.py depth --url <graphql_endpoint> [--max-depth 10]
Core Functions
run_introspection(url, headers) — Execute __schema introspection query
INTROSPECTION_QUERY = """
{
__schema {
queryType { name }
mutationType { name }
subscriptionType { name }
types {
name
kind
fields {
name
type { name kind ofType { name kind } }
args { name type { name kind } }
}
}
}
}
"""
def run_introspection(url, headers=None):
"""Execute full introspection query and extract schema details."""
resp = requests.post(
url,
json={"query": INTROSPECTION_QUERY},
headers=headers or {},
timeout=30,
)
resp.raise_for_status()
schema = resp.json().get("data", {}).get("__schema", {})
types = [t for t in schema.get("types", []) if not t["name"].startswith("__")]
queries = []
mutations = []
sensitive_fields = []
for t in types:
for field in (t.get("fields") or []):
if t["name"] == schema.get("queryType", {}).get("name"):
queries.append(field["name"])
if t["name"] == schema.get("mutationType", {}).get("name"):
mutations.append(field["name"])
if any(kw in field["name"].lower() for kw in SENSITIVE_PATTERNS):
sensitive_fields.append({"type": t["name"], "field": field["name"]})
return {
"types_count": len(types),
"queries": queries,
"mutations": mutations,
"sensitive_fields": sensitive_fields,
"introspection_enabled": True,
}
test_depth_limit(url, max_depth, headers) — Test query depth enforcement
def test_depth_limit(url, max_depth=15, headers=None):
"""Send increasingly nested queries to detect missing depth limits."""
results = []
for depth in range(1, max_depth + 1):
# Build a nested query using __typename
nested = "{ __typename " * depth + "}" * depth
query = f"query DepthTest {nested}"
try:
resp = requests.post(
url,
json={"query": query},
headers=headers or {},
timeout=10,
)
status = resp.status_code
has_errors = "errors" in resp.json()
results.append({
"depth": depth,
"status": status,
"blocked": has_errors and status != 200,
})
if has_errors:
return {
"max_allowed_depth": depth - 1,
"depth_limit_enforced": True,
"results": results,
}
except requests.Timeout:
return {
"max_allowed_depth": depth - 1,
"depth_limit_enforced": True,
"reason": "timeout",
"results": results,
}
return {
"max_allowed_depth": max_depth,
"depth_limit_enforced": False,
"severity": "high",
"detail": f"No depth limit detected up to {max_depth} levels",
"results": results,
}
test_batch_query(url, headers) — Test for batching attacks
def test_batch_query(url, headers=None):
"""Test if the endpoint allows batched queries (alias-based brute force)."""
batch = [
{"query": '{ alias0: __typename }'},
{"query": '{ alias1: __typename }'},
{"query": '{ alias2: __typename }'},
]
resp = requests.post(url, json=batch, headers=headers or {}, timeout=10)
return {
"batch_supported": resp.status_code == 200 and isinstance(resp.json(), list),
"responses": len(resp.json()) if isinstance(resp.json(), list) else 0,
}
Sensitive Field Patterns
SENSITIVE_PATTERNS = [
"password", "token", "secret", "credential", "ssn",
"credit_card", "api_key", "apikey", "private_key",
"auth", "session", "otp", "pin", "cvv",
]
Output Format
{
"url": "https://api.example.com/graphql",
"introspection_enabled": true,
"types_count": 45,
"queries": ["users", "orders", "admin_dashboard"],
"mutations": ["createUser", "deleteAccount", "updatePassword"],
"sensitive_fields": [
{"type": "User", "field": "password_hash"},
{"type": "Session", "field": "auth_token"}
],
"depth_limit": {
"enforced": false,
"max_tested": 15,
"severity": "high"
},
"batch_queries": {
"supported": true,
"severity": "medium"
}
}