graphql攻击思路

了解

GraphQL 是一种由 Facebook 开发的用于 API 查询语言和运行时的数据查询语言。它允许客户端指定所需的数据结构和内容,从而有效地获取多个资源的数据。相比于传统的 RESTful API,GraphQL 具有更灵活的特性,客户端可以按需获取特定字段的数据,而不是在每个端点上预定义的数据结构。

可以直接看数据包,更能直观的了解graphql,比如hackerone就是用的graphql

请求:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
POST /graphql HTTP/2
Host: hackerone.com
Cookie:
Content-Length: 341
Sec-Ch-Ua: "Google Chrome";v="119", "Chromium";v="119", "Not?A_Brand";v="24"
X-Csrf-Token:
Sec-Ch-Ua-Mobile: ?0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36
Content-Type: application/json
X-Product-Feature: details
Accept: */*
X-Product-Area: reports
Sec-Ch-Ua-Platform: "Windows"
Origin: https://hackerone.com
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer:
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9

{"operationName":"AppQuery","variables":{"product_area":"reports","product_feature":"details"},"query":"query AppQuery {\n maintenance_banner {\n id\n start_at\n end_at\n __typename\n }\n session {\n id\n __typename\n }\n me {\n id\n unreadNotificationCount: unread_notification_count\n __typename\n }\n}\n"}

operationName我的理解是请求名,比如登录、查询之类的功能标识名称

variables就是参数,类似查询的范围{“product_area”:”reports”,”product_feature”:”details”},查询的参数和返回包的数据对应 query查询的数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
query AppQuery {
maintenance_banner {
id
start_at
end_at
__typename
}
session {
id
__typename
}
me {
id
unreadNotificationCount: unread_notification_count
__typename
}
}

响应:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
HTTP/2 200 OK
Date: Tue, 14 Nov 2023 16:58:10 GMT
Content-Type: application/json; charset=utf-8
Cache-Control: no-store
Content-Disposition: inline; filename="response."
Vary: Accept
X-Request-Id:
Etag:
Set-Cookie:
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
X-Xss-Protection: 1; mode=block
X-Download-Options: noopen
X-Permitted-Cross-Domain-Policies: none
Referrer-Policy: strict-origin-when-cross-origin
Expect-Ct: enforce, max-age=86400
Content-Security-Policy:
Cf-Cache-Status:
Server: cloudflare
Cf-Ray:

{"data":{"maintenance_banner":null,"session":{"id":"Z2lkOi8vaGFja2Vyb25lL09iamVjdHM6OlNlc3Npb24vc3RhdGlj","__typename":"Session"},"me":{"id":"Z2lkOi8vaGFja2Vyb25lL1VzZXIvMTMxNzM0Mg==","unreadNotificationCount":0,"__typename":"User"}}}

识别graphql

/graphql
/graphql/console
/graphql.php
/graphiql.php
/explorer
/altair
/playground

字典

https://github.com/danielmiessler/SecLists/blob/master/Discovery/Web-Content/graphql.txt

ffuf语句

1
ffuf -w graphql.txt -u https://target/FUZZ 

可以使用Nuclei来检测GraphQL接口

模板可以使用如下:

https://github.com/projectdiscovery/nuclei-templates/blob/master/technologies/graphql-detect.yaml

1
2
3
4
5
#单个目标
nuclei -t graphql-detect.yaml -u https://example.com

# 多目标
nuclei -t graphql-detect.yaml -l target_domains.txt

指纹识别

可以使用: https://github.com/dolevf/graphw00f

1
python3 main.py -f -d -t http://localhost:5000

或者burp搜索graphql接口

工具

graphql有一个内省模式,查询payload,.没启用返回就会报错

https://gist.github.com/craigbeck/b90915d49fda19d5b2b17ead14dcd6da

1
2
3
4
5
6
7
	{
__schema {
types {
name
}
}
}

OR:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
{
__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
}}}}}}}}

存在内省可以使用工具进行扫描:

Burp-InQL进行分析

浏览器插件Altair GraphQL Client https://chrome.google.com/webstore/detail/altair-graphql-client/flnheeellpciglgpaodhkhmapeljopja

自动化测试 https://github.com/dolevf/graphql-cop

没有内省可以用工具进行爆破扫描:

https://github.com/nikitastupin/clairvoyance

clairvoyance 扫描出来会有一个json文件,可以用 vovager进行分析 https://graphql-kit.com/graphql-voyager/

生成文档用于检索 2fd/graphdoc: Static page generator for documenting GraphQL Schema (github.com)

攻击思路

https://www.acceis.fr/graphql-for-pentesters/

https://github.com/Escape-Technologies/awesome-graphql-security