Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/database/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何防止GraphQL/Apollo服务器上的嵌套攻击?_Graphql_Graphql Js_Apollo - Fatal编程技术网

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

如何防止GraphQL/Apollo服务器上的嵌套攻击?,graphql,graphql-js,apollo,Graphql,Graphql Js,Apollo,如何通过以下查询防止针对Apollo服务器的嵌套攻击: { authors { firstName posts { title author { firstName posts{ title author { firstName posts { title [n author]

如何通过以下查询防止针对Apollo服务器的嵌套攻击:

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

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

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

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

  • 查询验证:在每个GraphQL服务器中,运行查询的第一步是验证-这是服务器尝试确定查询中是否存在任何严重错误的地方,这样,如果我们发现前面有一些语法错误或无效参数,就可以避免使用实际的服务器资源。GraphQLJS的格式与ESLint非常相似。就像需要检测规则一样,可以编写验证规则来检测嵌套过多的查询,并在验证阶段拒绝它们
  • 查询超时:如果无法检测到查询在静态上过于资源密集(甚至浅查询也可能非常昂贵!),那么我们可以简单地在查询执行中添加超时。这有几个好处:(1)这是一个不难推理的硬限制,(2)这也有助于解决一个后端响应时间过长的情况。在许多情况下,你的应用程序的用户更喜欢一个缺少的字段,而不是等待10秒以上才能得到响应
  • 查询白名单:这可能是最复杂的方法,但您可以提前编译允许查询的列表,并根据该列表检查任何传入查询。如果您的查询是完全静态的(您不使用中继之类的工具在客户机上生成任何动态查询),那么这是最可靠的方法。您可以使用自动化工具在应用程序部署时从应用程序中提取查询字符串,以便在开发过程中编写您想要的任何查询,但在生产过程中只允许通过您想要的查询。这种方法的另一个好处是,您可以完全跳过查询验证,因为您知道所有可能的查询都已经有效。要了解静态查询和白名单的更多好处,请阅读以下文章:
  • 查询成本限制:(在编辑中添加)与查询超时类似,您可以在查询执行期间将成本分配给不同的操作,例如数据库查询,并限制客户端每次查询能够使用的总成本。这可以与限制单个查询的最大并行性相结合,这样可以防止客户端向后端发送启动数千个并行请求的内容
  • (1) 特别是(2)可能是每个GraphQL服务器在默认情况下都应该具备的功能,特别是因为许多新开发人员可能没有意识到这些问题。(3) 仅适用于某些类型的应用程序,但在有非常严格的性能或安全要求时,这可能是一个不错的选择。

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


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

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

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


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

    对于您可以使用的查询成本限制


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

    不要错过出色的响应。您知道有什么工具可以检测GraphQL中的循环依赖关系吗?我还要强调,另一个大问题是记忆力衰退。Posts->Author->Post层次结构中更深的每一层都是一个乘数(即1个Author拥有5个Posts->5个authors拥有25个Posts->25个authors拥有125个Posts,等等),它不仅将SQL/查询复合到基础数据源,还将堆分配复合到发送回响应。几个级别的深度很容易耗尽几GB的RAM,并使服务器完全崩溃。1个查询可以删除V8!我认为这是(2)和(3)将有帮助的地方。首先,您可以简单地限制单个查询对数据库的请求量(有点像超时)。第二,您可以让您的服务器在生产环境中只接受预先批准的查询,请参阅此处了解更多详细信息:注意:GraphQL Ruby内置了查询深度和复杂性分析器。我不确定其他语言的实现。