コンテンツにスキップ

Field Duplication in GraphQL API

GraphQL APIにおけるフィールドの重複

説明

GraphQLにおけるフィールドの重複は、攻撃者が同じフィールドを繰り返し要求するクエリを送信し、サーバーの処理能力を過負荷にする場合に発生します。

GraphQLでは、クライアントはクエリ内で同じフィールドを複数回含め、複数のフィールドを要求できます。しかし、フィールドの過度な重複は、サーバーのリソースを消費することにより、サービス拒否(DoS)攻撃を引き起こす可能性があります。これにより、パフォーマンスが低下したり、サービスが停止したりする可能性があります。 例:

query overload {
  user {
    id
    id
    id
    id
    id
    ...
  }
}

フィールドの重複によるセキュリティ上の影響:

  • サービス拒否(Denial of Service): クエリ内で同じフィールドを重複させることで、攻撃者はサーバーに同じリクエストを繰り返し処理させ、過剰なリソースの使用や潜在的なサービスのクラッシュを引き起こす可能性があります。
  • リソースの枯渇(Resource Exhaustion): エイリアスの過負荷と同様に、この攻撃はCPUとメモリの使用率の急増を引き起こし、システムを遅延させ、全体的なパフォーマンスに影響を与える可能性があります。
  • サービスの中断: 軽減されない場合、フィールドの重複攻撃により、正当なユーザーがGraphQL APIを利用できなくなり、システムのダウンタイムやサービスの低下を招く可能性があります。

推奨事項

フィールドの重複攻撃のリスクを軽減するには、以下の手順を実行できます:

  • クエリの複雑さの制限を実装する: 重複するフィールドをクエリの全体的なコストの一部と見なすクエリの複雑さのルールを適用します。これにより、処理される重複フィールドの数が制限され、サーバーをリソースの枯渇から保護できます。
  • フィールドの繰り返しの制限: 単一のGraphQLクエリでフィールドを重複できる回数にサーバー側の制限を構成します。GraphQL Armorのようなツールを使用して、このような制限を適用し、フィールドの重複による過負荷を防ぐことができます。
 // Configuring for GraphQL Armor
 GraphQLArmorConfig({
         maxFieldDuplicates: {
    // Enable or disable the plugin | default: true
             enabled: true,

    // Set the maximum number of field duplications allowed per query | default: 10
             n: 10,

    // Callbacks to execute when a query is accepted
             onAccept: [],

    // Callbacks to execute when a query is rejected
             onReject: [],

    // Propagate rejection details to the client | default: true
             propagateOnRejection: true,
                 }
             })
 import graphql
 from graphql.language import ast
 from graphql.language import parser
 from settings import api
 def validate_field_duplicates(query: str) -> None:
     """
         This validation prevents the execution of queries containing excessive
         duplicated fields to avoid overloading the server.
         """
         class FieldDuplicationParser(parser.Parser):
             def parse_duplicates(self) -> list[ast.FieldNode]:
                     field_counts = {}
                         while self.peek(graphql.TokenKind.NAME):
                             field_name = self.parse_field().name.value
                                 field_counts[field_name] = field_counts.get(field_name, 0) + 1
                                 if field_counts[field_name] > api.API_MAX_FIELD_DUPLICATES:
                                     raise graphql.GraphQLError("Exception - Max field duplicates exceeded")
                                 return []
                 ast_parser = FieldDuplicationParser(query)
         ast_parser.parse_document()

リンク

基準

  • CWE_TOP_25:
    • CWE_400
  • PCI_STANDARDS:
    • REQ_6_2
    • REQ_6_4
    • REQ_11_3
  • OWASP_MASVS_L2:
    • MSTG_PLATFORM_2
  • OWASP_ASVS_L2:
    • V4_1_3
    • V4_1_5
    • V5_3_3
    • V5_3_4
    • V9_1_1
    • V9_1_2
    • V12_1_1
    • V12_1_2
  • OWASP_ASVS_L3:
    • V4_1_3
    • V4_1_5
    • V5_3_3
    • V5_3_4
    • V9_1_1
    • V9_1_2
    • V12_1_1
    • V12_1_2
    • V12_1_3
  • SOC2_CONTROLS:
    • CC_2_1
    • CC_4_1
    • CC_7_1
    • CC_7_2
    • CC_7_4
    • CC_7_5
    • CC_9_1
  • HIPAA_CONTROLS:
    • SECURITY212
    • SECURITY213