Aller au contenu

GraphQL Authorization Misconfiguration

Mauvaise configuration des autorisations GraphQL

Description

Une mauvaise configuration des autorisations GraphQL (GraphQL Authorization Misconfiguration) est une vulnérabilité de sécurité critique qui se produit lorsqu'une API GraphQL n'applique pas de manière cohérente et exhaustive les contrôles d'accès sur l'ensemble de ses opérations et modèles de données. Cette négligence permet à des utilisateurs non autorisés d'accéder, de modifier ou de supprimer des informations au-delà des permissions qui leur sont accordées, compromettant potentiellement la sécurité du système dans son ensemble. Les principales caractéristiques de cette vulnérabilité incluent des contrôles d'accès incohérents, où différentes requêtes (queries) ou mutations pour des données similaires présentent des niveaux de vérification d'autorisation variables ; un schéma trop permissif qui expose des champs ou des opérations sensibles sans restrictions appropriées ; et l'absence de limites de profondeur pour les requêtes, ce qui se traduit par un manque de mécanismes pour prévenir les requêtes trop gourmandes en ressources ou excessivement imbriquées.

Conséquences

  1. Accès et manipulation de données non autorisés :
  2. Les attaquants peuvent récupérer des informations sensibles telles que des données personnelles d'utilisateurs, des dossiers financiers ou des informations commerciales exclusives.
  3. Des utilisateurs malveillants peuvent altérer ou supprimer des données critiques, affectant ainsi l'intégrité du système et la confiance des utilisateurs.

  4. Élévation de privilèges potentielle :

  5. En exploitant des requêtes ou des mutations mal configurées, les attaquants pourraient obtenir des privilèges administratifs.
  6. Un mouvement latéral au sein du système devient possible, permettant l'accès à d'autres zones restreintes.

  7. Compromission de l'intégrité du système :

  8. La fiabilité et l'exactitude de l'ensemble des données sont remises en question.
  9. Des violations de conformité peuvent se produire, particulièrement en ce qui concerne les réglementations sur la protection des données comme le GDPR ou le CCPA.

  10. Exfiltration de données :

  11. Le vol de données à grande échelle devient réalisable grâce à des requêtes minutieusement élaborées.
  12. Des informations de veille concurrentielle ou des bases de données d'utilisateurs pourraient être extraites sans être détectées.

  13. Atteinte à la réputation :

  14. La divulgation publique de telles vulnérabilités peut entraîner une perte de confiance des utilisateurs et de potentielles conséquences juridiques.

Exemple de code

  class UserType(DjangoObjectType):
    class Meta:
      model = User
      fields = ("id", "username", "email")

  class OrganizationType(DjangoObjectType):
    class Meta:
      model = Organization
      fields = ("id", "name", "users")

  class Query(graphene.ObjectType):
  all_users = graphene.List(UserType)
  organization = graphene.Field(OrganizationType, id=graphene.ID(required=True))

  def resolve_all_users(self, info):
    user = info.context.user
    if not user.is_authenticated:
      raise graphene.GraphQLError("Authentication required")
    return User.objects.all()

  def resolve_organization(self, info, id):
    try:
      org = Organization.objects.get(id=id)
    except Organization.DoesNotExist:
      raise graphene.GraphQLError("Organization not found")

    return org
Dans cet exemple, remarquez que bien que la Users Query implémente un contrôle d'accès, la Organization Query ne le fait pas. Puisque la requête sur l'organisation expose l'attribut imbriqué des utilisateurs, un attaquant peut l'utiliser pour accéder à des informations qui lui étaient refusées lors d'une requête directe.

Exemples de requêtes :

# Requête sécurisée
query {
  allUsers {
    id
    username
    email
  }
}

# Requête vulnérable
query {
  organization(id: "123") {
    id
    name
    users {
      id
      username
      email
    }
  }
}

Recommandation

Bonnes pratiques de mitigation

  1. Implémenter une autorisation cohérente côté serveur :
  2. Utilisez des middlewares ou des décorateurs pour appliquer les contrôles d'accès de manière uniforme.
  3. Exemple :

    @require_permission('admin')
    def resolve_sensitive_data(self, info):
        # Seuls les administrateurs peuvent accéder à ce résolveur
        pass
    
  4. Utiliser des permissions au niveau des champs :

  5. Définissez et appliquez des contrôles d'accès au niveau de chaque champ.
  6. Exemple avec graphene-django :

    class UserType(DjangoObjectType):
        class Meta:
            model = User
            fields = ('id', 'username', 'email')
    
        @staticmethod
        def resolve_email(parent, info):
            if info.context.user.has_permission('view_email'):
                return parent.email
            return None
    
  7. Utiliser des scalaires personnalisés pour les données sensibles :

  8. Implémentez des types scalaires personnalisés intégrant des vérifications d'autorisation.

  9. Désactiver ou limiter l'introspection :

  10. Dans les environnements de production, désactivez l'introspection ou limitez-la uniquement aux utilisateurs authentifiés et autorisés.

  11. Audits et analyses de sécurité réguliers :

  12. Effectuez des examens approfondis de votre schéma GraphQL, de vos résolveurs et de vos mécanismes de contrôle d'accès.

En s'attaquant à ces causes profondes et en implémentant des mécanismes d'autorisation robustes, les développeurs peuvent réduire considérablement le risque de mauvaises configurations des autorisations GraphQL et créer des API GraphQL plus sécurisées.

Liens

Normes

  • CCPA:
    • CCPA_1798_150
  • CWE_TOP_25:
    • CWE_862
  • OWASP_ASVS_L3:
    • V1_2_4
    • V4_1_3
    • V13_4_1
    • V13_4_2
  • SOC2_CONTROLS:
    • CC_6_3