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

jbo*_*the 50 apollo graphql graphql-js

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

{
  authors {
    firstName
    posts {
      title
      author {
        firstName
        posts{
          title
          author {
            firstName
            posts {
              title
              [n author]
                [n post]
            }
          }
        }
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

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

stu*_*ilo 54

截至撰写本文时,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)仅适用于某些类型的应用程序,但在有非常严格的性能或安全要求时可能是一个不错的选择.


And*_*son 12

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

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