graphql-php OverlappingFieldsCanBeMerged Quadratic Complexity Vulnerability
The `OverlappingFieldsCanBeMerged` validation rule in `webonyx/graphql-php` has an `O(n^2 x m^2)` worst-case complexity due to flattened inline fragments, leading to potential resource exhaustion.
The OverlappingFieldsCanBeMerged validation rule in webonyx/graphql-php is vulnerable to a quadratic complexity issue due to how it handles inline fragments. Specifically, the pairwise comparison loop within the collectConflictsWithin function can lead to an O(n^2 x m^2) worst-case scenario when processing queries with nested inline fragments. A 364 KB query with 200 outer and 100 inner inline fragments was observed to consume 117 seconds of CPU time per request on webonyx/graphql-php@v15.31.4 running on PHP 8.3.30. The existing named-fragment cache (CVE-2023-26144) does not cover inline fragments, making the system vulnerable to denial-of-service attacks through resource exhaustion. This affects applications using the standard validation pipeline, including Lighthouse, Overblog/GraphQLBundle, wp-graphql, and Drupal GraphQL.
Attack Chain
- An attacker crafts a GraphQL query with a large number of nested inline fragments.
- The query is submitted to a
webonyx/graphql-phpapplication. - The
DocumentValidator::validate()function invokes the default rules, includingOverlappingFieldsCanBeMerged. - Within
OverlappingFieldsCanBeMerged.php, theinternalCollectFieldsAndFragmentNamesfunction flattens inline fragments into the parent$astAndDefsmap, increasing the size of the map. - The
collectConflictsWithinfunction iterates through the flattened fields, performing anO(n^2)pairwise comparison of fields. - The
findConflictfunction is recursively called for sub-selections, compounding the cost toO(n^2 x m^2). - Due to the absence of a comparison budget or validation timeout, the validation process consumes excessive CPU resources.
- The PHP worker process becomes pinned, leading to potential denial of service via worker pool exhaustion.
Impact
A successful attack can lead to a denial of service (DoS) due to the exhaustion of server resources. A single 364 KB query can consume 117 seconds of CPU time, potentially exhausting the php-fpm worker pool. Systems with default configurations, such as Lighthouse/Laravel deployments, may be vulnerable even with max_execution_time limits, as the worker may burn significant CPU time before being terminated. Exploitation can bypass body-size limits and WAF rules via gzip compression, as the decompressed payload is much larger than the compressed one. The vulnerability affects all applications using the standard validation pipeline in webonyx/graphql-php versions prior to 15.32.2.
Recommendation
- Upgrade to
webonyx/graphql-phpversion 15.32.2 or later, which includes a fix that addresses this vulnerability. - Implement a comparison budget in
OverlappingFieldsCanBeMergedto limit the number of comparisons performed during validation, as described in the remediation options. - Consider capping inline-fragment flattening in
internalCollectFieldsAndFragmentNamesto prevent excessive growth of the$astAndDefsmap, as outlined in the remediation options. - Deploy the Sigma rule
Detect GraphQL PHP Excessive Validation Timeto identify potential exploitation attempts by monitoring the execution time of GraphQL validation processes.
Detection coverage 2
Detect GraphQL PHP Excessive Validation Time
highDetects excessive validation time in PHP processes, which may indicate a GraphQL resource exhaustion attack.
Detect GraphQL PHP Spawning Many Processes
mediumDetects a high number of PHP processes being spawned, which may indicate a GraphQL resource exhaustion attack.
Detection queries are kept inside the platform. Get full rules →