61

如何使用以下查询防止对 Apollo 服务器的嵌套攻击:

{
  authors {
    firstName
    posts {
      title
      author {
        firstName
        posts{
          title
          author {
            firstName
            posts {
              title
              [n author]
                [n post]
            }
          }
        }
      }
    }
  }
}

换句话说,如何限制查询中提交的递归数?这可能是一个潜在的服务器漏洞。

4

5 回答 5

61

在撰写本文时,GraphQL-JS 或 Apollo Server 中还没有内置功能来处理这个问题,但随着 GraphQL 变得越来越流行,它肯定应该有一个简单的解决方案。这个问题可以通过堆栈的多个级别的几种方法来解决,并且还应该始终与速率限制结合使用,这样人们就不能向您的服务器发送太多查询(这也是 REST 的一个潜在问题)。

我将仅列出我能想到的所有不同方法,并且由于这些解决方案已在各种 GraphQL 服务器中实现,因此我将尝试使此答案保持最新。其中有些非常简单,有些则更复杂。

  1. 查询验证:在每个 GraphQL 服务器中,运行查询的第一步是验证——这是服务器尝试确定查询中是否有任何严重错误的地方,这样我们就可以避免使用实际的服务器资源,如果我们能找到的话前面有一些语法错误或无效参数。GraphQL-JS 附带了一系列默认规则,其格式与 ESLint 非常相似。就像有一条规则可以检测片段中的无限循环一样,可以编写一个验证规则来检测嵌套过多的查询并在验证阶段拒绝它们。
  2. 查询超时:如果无法检测到静态查询过于占用资源(也许即使是浅查询也可能非常昂贵!),那么我们可以简单地为查询执行添加超时。这有几个好处:(1) 这是一个不难推理的硬性限制,(2) 这也有助于解决其中一个后端响应时间过长的情况。在许多情况下,您的应用程序的用户更喜欢缺少字段,而不是等待 10 多秒才能获得响应。
  3. 查询白名单:这可能是最复杂的方法,但您可以提前编译允许查询的列表,并根据该列表检查任何传入的查询。如果您的查询是完全静态的(您不会在客户端上使用 Relay 之类的东西生成任何动态查询),这是最可靠的方法。您可以在部署应用程序时使用自动化工具从应用程序中提取查询字符串,以便在开发中编写您想要的任何查询,但在生产中只允许您想要的查询。这种方法的另一个好处是您可以完全跳过查询验证,因为您知道所有可能的查询都已经有效。有关静态查询和白名单的更多好处,请阅读这篇文章:https://dev-blog.apollodata.com/5-benefits-of-static-graphql-queries-b7fa90b0b69a
  4. 查询成本限制:(在编辑中添加)与查询超时类似,您可以在查询执行期间为不同的操作分配成本,例如数据库查询,并限制客户端每次查询能够使用的总成本。这可以与限制单个查询的最大并行度相结合,这样您就可以防止客户端向您的后端发送启动数千个并行请求的内容。

(1) 和 (2) 可能是每个 GraphQL 服务器默认应该具备的,特别是因为许多新开发人员可能没有意识到这些问题。(3) 仅适用于某些类型的应用程序,但在性能或安全要求非常严格时可能是一个不错的选择。

于 2016-05-20T05:20:17.547 回答
15

为了补充 stubailo 回答中的第 (4) 点,这里有一些 Node.js 实现,它们对传入的 GraphQL 文档施加了成本和深度限制。

这些是补充验证阶段的自定义规则。

于 2017-08-09T23:57:01.553 回答
4

查询白名单的一个变体是查询签名

在构建过程中,每个查询都使用与服务器共享但不与客户端捆绑的秘密进行加密签名。然后在运行时服务器可以验证查询是否真实。

与白名单相比的优势在于,在客户端编写查询不需要对服务器进行任何更改。如果多个客户端访问同一服务器(例如 Web、桌面和移动应用程序),这尤其有价值。

于 2017-11-29T16:04:42.430 回答
2

对于查询成本限制,您可以使用graphql-cost-analysis

这是一个验证规则,它在执行之前解析查询。在您的 GraphQL 服务器中,您只需为您想要的 Schema Type Map 的每个字段分配一个成本配置。

于 2018-01-09T10:30:16.163 回答
2

不要错过graphql-rate-limit一个 GraphQL 指令来为您的查询或突变添加基本但细化的速率限制。

于 2019-01-18T19:06:08.710 回答