Aller au contenu

Circular Fragment in GraphQL

Fragment circulaire dans GraphQL

Description

Les fragments circulaires dans GraphQL désignent une situation où les fragments dans les requêtes GraphQL se référencent mutuellement, entraînant une référence circulaire. Cela peut provoquer des problèmes tels que des boucles infinies, un épuisement des ressources et des attaques par déni de service (DoS). Un attaquant pourrait exploiter cela pour surcharger le serveur GraphQL, le rendant indisponible ou lent pour les utilisateurs légitimes.

Impact sur la sécurité des fragments circulaires dans GraphQL :

1. Déni de service (DoS) : Les références de fragments circulaires peuvent amener le serveur à résoudre les requêtes de manière interminable, consommant des ressources excessives pour finalement planter ou ralentir. 2. Épuisement des ressources : Les boucles de fragments infinies peuvent entraîner une utilisation élevée du CPU et de la mémoire, provoquant un épuisement des ressources qui dégrade les performances de l'application ou du serveur. 3. Exploitation de la complexité des requêtes : Les attaquants peuvent concevoir des requêtes complexes avec des fragments circulaires pour exploiter l'absence de limites de profondeur ou de récursivité dans le serveur GraphQL.

Un exemple basique de fragment circulaire pourrait ressembler à ceci :

fragment UserFields on User {
  name
  ...MoreUserFields
}

fragment MoreUserFields on User {
  email
  ...UserFields
}

Dans cet exemple, UserFields référence MoreUserFields, et MoreUserFields référence UserFields, créant ainsi une référence circulaire.

Recommandation

Pour atténuer le risque de fragments circulaires dans GraphQL, envisagez les étapes suivantes :

1. Détection des fragments circulaires via l'analyse du schéma

Implémentez une analyse statique sur votre schéma GraphQL et vos requêtes pour détecter et prévenir les références circulaires avant qu'elles ne puissent être exploitées. Certaines bibliothèques de serveur GraphQL fournissent des outils pour analyser les schémas.

  • Tooling : Utilisez des outils de linting GraphQL tels que GraphQL Code Generator ou GraphQL Inspector pour détecter les fragments circulaires et éviter qu'ils n'atteignent la production.

Exemple d'utilisation de GraphQL Code Generator :

npm install @graphql-codegen/cli
npx graphql-codegen init

Vous pouvez configurer le générateur de code pour produire des validations de schéma qui détectent les problèmes potentiels de fragments circulaires dans vos requêtes GraphQL.

2. Implémenter l'analyse du coût des requêtes

Utilisez l'analyse de la complexité des requêtes pour attribuer un "coût" à chaque champ, fragment ou requête. Lorsqu'une requête ou un fragment dépasse un seuil de coût prédéfini, il peut être automatiquement rejeté.

  • Tooling : Vous pouvez utiliser des bibliothèques telles que graphql-query-complexity pour calculer le coût des requêtes et limiter l'impact des fragments circulaires.

Exemple en JavaScript utilisant graphql-query-complexity :

const { getComplexity, simpleEstimator } = require('graphql-query-complexity');

const server = new ApolloServer({
  schema,
  validationRules: [
    queryComplexity({
      estimators: [
        simpleEstimator({ defaultComplexity: 1 })
      ],
      maximumComplexity: 1000,  // Queries that exceed this complexity will be rejected
      onComplete: (complexity) => {
        console.log('Query Complexity:', complexity);
      },
    }),
  ],
});

3. Appliquer des limites de profondeur et de récursivité

Certaines implémentations de serveur GraphQL vous permettent de définir des limites de profondeur et de récursivité des requêtes pour prévenir l'épuisement des ressources. Cela permet d'éviter les boucles infinies causées par des fragments circulaires.

  • Tooling : Apollo Server, par exemple, prend en charge les limites de profondeur des requêtes, ce qui peut empêcher une récursivité excessive.

Exemple d'utilisation de la limite de profondeur de requête dans Apollo Server :

const { ApolloServer } = require('apollo-server');
const depthLimit = require('graphql-depth-limit');

const server = new ApolloServer({
  schema,
  validationRules: [depthLimit(5)],  // Set query depth limit to 5
});

4. Utiliser les fragments judicieusement

Évitez de surutiliser les fragments dans des requêtes complexes. Leur utilisation excessive peut entraîner une dégradation des performances et ouvre la voie aux références circulaires. Envisagez plutôt de diviser les requêtes complexes en plusieurs requêtes plus petites.

  • Recommendation : Révisez la conception des requêtes et limitez l'utilisation des fragments à des éléments de données modulaires et spécifiques.

Exemple :

query {
  user(id: "1") {
    name
    email
    posts {
      title
      content
    }
  }
}

Plutôt que d'imbriquer plusieurs fragments les uns dans les autres, utilisez une requête plus simple comme celle-ci.

Liens

Normes

  • CWE_TOP_25:
    • CWE_400
  • PCI_STANDARDS:
    • REQ_6_2
    • REQ_6_4
    • REQ_11_3
  • OWASP_MASVS_L2:
    • MSTG_PLATFORM_2
  • OWASP_ASVS_L3:
    • V13_4_1
  • 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