Skip to content

Field Duplication in GraphQL API

Field Duplication in GraphQL API

Description

Field Duplication in GraphQL occurs when an attacker sends a query that requests the same field repeatedly, overloading the server's processing capabilities.

In GraphQL, clients can request multiple fields in a query, including the same field multiple times. However, excessive duplication of fields can result in a Denial of Service (DoS) attack by consuming server resources. This can degrade performance or cause a service outage. Example:

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

Security Impact of Field Duplication:

  • Denial of Service: By duplicating the same field in a query, attackers can force the server to repeatedly process the same request, leading to excessive resource use and potential service crashes.
  • Resource Exhaustion: Similar to Alias Overloading, this attack can cause spikes in CPU and memory usage, slowing down the system and affecting overall performance.
  • Service Disruption: If not mitigated, Field Duplication attacks can make the GraphQL API unavailable to legitimate users, leading to system downtime or degraded service.

Recommendation

To mitigate the risk of Field Duplication attacks, you can take the following steps:

  • Implement Query Complexity Limits: Enforce query complexity rules that consider duplicated fields as part of the overall cost of a query. This helps in limiting the number of duplicate fields processed, thus protecting the server from resource exhaustion.
  • Limit Field Repetitions: Configure server-side limits on the number of times a field can be duplicated in a single GraphQL query. You can use tools like GraphQL Armor to enforce such limits and prevent field duplication overloading.
 // 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()

Standards

  • 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