Translated ['src/network-services-pentesting/pentesting-web/graphql.md']

This commit is contained in:
Translator 2025-01-22 23:11:39 +00:00
parent 11169a6406
commit 31cd565438

View File

@ -8,7 +8,7 @@ GraphQL 被 **强调** 为 REST API 的 **高效替代方案**,提供了一种
## GraphQL 和安全性
随着包括 GraphQL 在内的新技术的出现,新安全漏洞也随之而来。一个关键点是 **GraphQL 默认不包含身份验证机制**。开发者有责任实施这些安全措施。没有适当的身份验证GraphQL 端点可能会向未认证的用户暴露敏感信息,构成重大安全风险。
随着新技术的出现,包括 GraphQL新的安全漏洞也随之出现。一个关键点是 **GraphQL 默认不包含身份验证机制**。开发者有责任实施这些安全措施。没有适当的身份验证GraphQL 端点可能会向未认证的用户暴露敏感信息,构成重大安全风险。
### 目录暴力攻击和 GraphQL
@ -23,11 +23,11 @@ GraphQL 被 **强调** 为 REST API 的 **高效替代方案**,提供了一种
- `/graphql/api`
- `/graphql/graphql`
识别开放的 GraphQL 实例可以检查支持的查询。这对于理解通过端点可访问的数据至关重要。GraphQL 的自省系统通过详细说明模式支持的查询来促进这一点。有关更多信息,请参阅 GraphQL 文档中的自省[**GraphQL: A query language for APIs.**](https://graphql.org/learn/introspection/)
识别开放的 GraphQL 实例可以检查支持的查询。这对于理解通过端点可访问的数据至关重要。GraphQL 的自省系统通过详细说明模式支持的查询来促进这一点。有关更多信息,请参阅 GraphQL 关于自省的文档:[**GraphQL: A query language for APIs.**](https://graphql.org/learn/introspection/)
### 指纹识别
工具 [**graphw00f**](https://github.com/dolevf/graphw00f) 能够检测服务器使用的 GraphQL 引擎,并打印一些对安全审计员有的信息。
工具 [**graphw00f**](https://github.com/dolevf/graphw00f) 能够检测服务器使用的 GraphQL 引擎,并打印一些对安全审计员有帮助的信息。
#### 通用查询 <a href="#universal-queries" id="universal-queries"></a>
@ -172,7 +172,7 @@ name
现在我们知道数据库中保存了哪种信息,让我们尝试 **提取一些值**
在自省中,您可以找到 **可以直接查询的对象**(因为您不能仅仅因为对象存在就查询它)。在下面的中,您可以看到 "_queryType_" 被称为 "_Query_",而 "_Query_" 对象的一个字段是 "_flags_",这也是一种对象类型。因此,您可以查询标志对象。
在自省中,您可以找到 **可以直接查询的对象**(因为您不能仅仅因为对象存在就查询它)。在下图中,您可以看到 "_queryType_" 被称为 "_Query_",而 "_Query_" 对象的一个字段是 "_flags_",这也是一种对象类型。因此,您可以查询标志对象。
![](<../../images/Screenshot from 2021-03-13 18-17-48.png>)
@ -180,7 +180,7 @@ name
![](<../../images/Screenshot from 2021-03-13 18-22-57 (1).png>)
您可以看到 "_Flags_" 对象由 **name****value** 组成。然后,您可以使用以下查询获取所有标志的名称和值:
您可以看到 "_Flags_" 对象由 **name****value** 组成。然后,您可以使用查询获取所有标志的名称和值:
```javascript
query={flags{name, value}}
```
@ -204,7 +204,7 @@ query = { hiddenFlags }
看起来它会使用类型为 _**Int**_ 的 "_**uid**_" 参数进行搜索。\
无论如何,我们已经知道,在 [Basic Enumeration](graphql.md#basic-enumeration) 部分提出了一个查询,显示了所有所需的信息:`query={__schema{types{name,fields{name, args{name,description,type{name, kind, ofType{name, kind}}}}}}}`
如果你阅读提供的图像,当我运行该查询时,你会看到 "_**user**_" 有一个类型为 _Int_**arg** "_**uid**_"。
如果你阅读提供的图像,当我运行该查询时,你会看到 "_**user**_" 有类型为 _Int_**arg** "_**uid**_"。
因此,通过一些轻量级的 _**uid**_ 暴力破解,我发现 _**uid**=**1** 时检索到了一个用户名和密码:\
`query={user(uid:1){user,password}}`
@ -219,11 +219,11 @@ query = { hiddenFlags }
**查询字符串转储技巧(感谢 @BinaryShadow\_**
如果你可以通过字符串类型进行搜索,例如:`query={theusers(description: ""){username,password}}`,并且你**搜索一个空字符串**,它将**转储所有数据**。 (_注意这个例子与教程的例子无关对于这个例子假设你可以通过一个名为 "**description**" 的字符串字段使用 "**theusers**" 进行搜索_).
如果你可以通过字符串类型进行搜索,例如:`query={theusers(description: ""){username,password}}`,并且你**搜索一个空字符串**,它将**转储所有数据**。 (_注意这个例子与教程的例子无关对于这个例子假设你可以通过一个名为 "**description**" 的字符串字段使用 "**theusers**" 进行搜索_)
### 搜索
在这个设置中,一个**数据库**包含**人员**和**电影**。**人员**通过他们的**电子邮件**和**姓名**进行识别;**电影**通过它们的**名称**和**评分**进行识别。**人员**可以互为朋友,也可以拥有电影,表示数据库中的关系。
在这个设置中,一个**数据库**包含**人员**和**电影**。**人员**通过他们的**电子邮件**和**姓名**进行识别;**电影**通过它们的**名称**和**评分**进行识别。**人员**可以互为朋友,并且也有电影,表示数据库中的关系。
你可以通过**姓名**搜索人员并获取他们的电子邮件:
```javascript
@ -233,7 +233,7 @@ email
}
}
```
您可以通过姓名搜索人员并获取他们订阅的电影:
您可以通过**姓名**搜索人员并获取他们**订阅****电影**
```javascript
{
searchPerson(name: "John Doe") {
@ -258,7 +258,7 @@ name
}
}r
```
或者甚至**使用别名的多个不同对象的关系**
或者甚至**使用别名的多个不同对象的关系**
```javascript
{
johnsMovieList: searchPerson(name: "John Doe") {
@ -285,11 +285,11 @@ name
**变更用于在服务器端进行更改。**
**自省**中,您可以找到**声明的** **变更**。在下图中,"_MutationType_" 被称为 "_Mutation_",而 "_Mutation_" 对象包含变更的名称(在本例中为 "_addPerson_"
**introspection** 中可以找到 **声明的** **变更**。在下图中,"_MutationType_" 被称为 "_Mutation_",而 "_Mutation_" 对象包含变更的名称(在本例中为 "_addPerson_"
![](<../../images/Screenshot from 2021-03-13 18-26-27 (1).png>)
在此设置中,**数据库**包含**人员**和**电影**。**人员**通过其**电子邮件**和**姓名**进行识别;**电影**通过其**名称**和**评分**进行识别。**人员**可以互为朋友,并且也可以拥有电影,表示数据库中的关系。
在此设置中,**数据库** 包含 **人员****电影**。**人员** 通过他们的 **电子邮件****姓名** 进行识别;**电影** 通过它们的 **名称****评分** 进行识别。**人员** 可以互为朋友,并且也可以拥有电影,表示数据库中的关系。
一个 **在数据库中创建新** 电影的变更可以如下所示(在此示例中,变更被称为 `addMovie`
```javascript
@ -353,7 +353,7 @@ releaseYear
越来越多的**graphql端点正在禁用自省**。然而当收到意外请求时graphql抛出的错误足以让像[**clairvoyance**](https://github.com/nikitastupin/clairvoyance)这样的工具重建大部分架构。
此外Burp Suite扩展[**GraphQuail**](https://github.com/forcesunseen/graphquail)扩展**观察通过Burp的GraphQL API请求**,并**构建**一个内部GraphQL**架构**每当它看到新的查询时。它还可以为GraphiQL和Voyager公开架构。当收到自省查询时该扩展返回一个假响应。因此GraphQuail显示了API中可用的所有查询、参数和字段。有关更多信息[**请查看此处**](https://blog.forcesunseen.com/graphql-security-testing-without-a-schema)。
此外Burp Suite扩展[**GraphQuail**](https://github.com/forcesunseen/graphquail) **观察通过Burp的GraphQL API请求**并**构建**一个内部GraphQL **架构**每当它看到新的查询时。它还可以为GraphiQL和Voyager公开架构。当收到自省查询时该扩展返回一个假响应。因此GraphQuail显示了API中可用的所有查询、参数和字段。有关更多信息[**请查看此处**](https://blog.forcesunseen.com/graphql-security-testing-without-a-schema)。
一个很好的**词表**可以在这里发现[**GraphQL实体**](https://github.com/Escape-Technologies/graphql-wordlist?)。
@ -397,13 +397,13 @@ ws.send(JSON.stringify(graphqlMsg))
```
### **发现暴露的 GraphQL 结构**
当 introspection 被禁用时,检查网站源代码中 JavaScript 库中预加载的查询是一种有用的策略。这些查询可以通过开发者工具中的 `Sources` 选项卡找到,提供有关 API 架构的见解,并揭示潜在的 **暴露敏感查询**。在开发者工具中搜索的命令是:
当 introspection 被禁用时,检查网站源代码中 JavaScript 库中预加载的查询是一种有用的策略。这些查询可以通过开发者工具中的 `Sources` 选项卡找到,提供有关 API 架构的见解,并揭示潜在的 **暴露敏感查询**。在开发者工具中搜索的命令是:
```javascript
Inspect/Sources/"Search all files"
file:* mutation
file:* query
```
## CSRF in GraphQL
## GraphQL中的CSRF
如果你不知道什么是CSRF请阅读以下页面
@ -459,7 +459,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”和一个用户变量,以便系统注册为新用户。
<figure><img src="../../images/GraphQLAuthBypassMethod.PNG" alt=""><figcaption></figcaption></figure>
@ -469,7 +469,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
@ -490,7 +490,7 @@ valid
### Alias Overloading
**Alias Overloading** 是一种 GraphQL 漏洞,攻击者通过为同一字段重载查询,使用多个别名,导致后端解析器重复执行该字段。这可能会使服务器资源过载,从而导致 **Denial of Service (DoS)**。例如,在下面的查询中,同一字段 (`expensiveField`) 被请求了 1,000 次,使用别名,迫使后端计算 1,000 次,可能会耗尽 CPU 或内存:
**Alias Overloading** 是一种 GraphQL 漏洞,攻击者通过为同一字段重载查询中的多个别名,导致后端解析器重复执行该字段。这可能会使服务器资源过载,从而导致 **Denial of Service (DoS)**。例如,在下面的查询中,同一字段 (`expensiveField`) 被请求了 1,000 次,使用别名强迫后端计算 1,000 次,可能会耗尽 CPU 或内存:
```graphql
# Test provided by https://github.com/dolevf/graphql-cop
curl -X POST -H "Content-Type: application/json" \