你如何防止对GraphQL / Apollo服务器的嵌套攻击?

时间:2016-05-20 03:29:53

标签: graphql graphql-js apollo

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

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

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

5 个答案:

答案 0 :(得分:48)

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

我将列出我能想到的所有不同方法,并且我会尽力使这个答案保持最新,因为这些解决方案是在各种GraphQL服务器中实现的。其中一些很简单,有些更复杂。

  1. 查询验证:在每个GraphQL服务器中,运行查询的第一步是验证 - 这是服务器尝试确定是否存在任何严重错误的位置查询,以便我们可以避免使用实际的服务器资源,如果我们可以预先发现有一些语法错误或无效的参数。 GraphQL-JS附带a selection of default rules,其格式与ESLint非常相似。就像有一条检测infinite cycles in fragments的规则一样,可以编写验证规则来检测嵌套过多的查询,并在验证阶段拒绝它们。
  2. 查询超时:如果无法检测到查询资源过于静态(即使是浅层查询也可能非常昂贵!),那么我们只需添加超时即可查询执行。这有一些好处:(1)这是一个不太难以推理的硬限制,(2)这也有助于其中一个后端花费不合理的长时间来响应的情况。在许多情况下,您的应用的用户会更喜欢缺少字段而不是等待10秒以上才能获得响应。
  3. 查询白名单:这可能是涉及最多的方法,但您可以提前编译允许的查询列表,并检查针对该列表的任何传入查询。如果您的查询是完全静态的(您不在客户端上使用Relay之类的任何动态查询生成),这是最可靠的方法。您可以使用自动化工具在部署时从应用程序中提取查询字符串,以便在开发过程中编写您想要的任何查询,但在生产中只会将您想要的查询通过。此方法的另一个好处是您可以完全跳过查询验证,因为您知道所有可能的查询都已有效。有关静态查询和白名单的更多好处,请阅读以下文章:https://dev-blog.apollodata.com/5-benefits-of-static-graphql-queries-b7fa90b0b69a
  4. 查询成本限制 :(在编辑中添加)与查询超时类似,您可以在查询执行期间为不同的操作分配成本,例如数据库查询,并限制客户端的总成本能够使用每个查询。这可以与限制单个查询的最大并行度相结合,这样就可以防止客户端向您的后端发送启动数千个并行请求的内容。
  5. (1)和(2)特别是默认情况下每个GraphQL服务器都应具有的功能,特别是因为许多新开发人员可能不会意识到这些问题。 (3)仅适用于某些类型的应用程序,但在有非常严格的性能或安全要求时可能是一个不错的选择。

答案 1 :(得分:11)

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

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

答案 2 :(得分:3)

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

在构建过程中,使用与服务器共享但未与客户端捆绑的密钥对每个查询进行加密签名。然后在运行时,服务器可以验证查询是否为正版。

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

答案 3 :(得分:2)

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

这是一个验证规则,可在执行查询之前解析查询。在GraphQL服务器中,您只需为所需的模式类型映射的每个字段分配成本配置。

答案 4 :(得分:1)

Don't miss graphql-rate-limit a GraphQL directive to add basic but granular rate limiting to your Queries or Mutations.