Lors d’un pentest d’application web, nous avons découvert une vulnérabilité liée à la configuration et à la mauvaise gestion des contrôles de droits sur GraphQL.

En profitant également d’une IDOR, cette vulnérabilité critique nous a permis de sortir du cloisonnement et d’accéder à des données appartenant à d’autres instances. Nous vous expliquons comment en présentant, dans un premier temps, les différentes étapes pour exploiter GraphQL avant d’exposer le cas concret rencontré lors du pentest.

Comment exploiter GraphQL ?

Commençons par une démonstration d’exploitation de GraphQL effectuée sur une application de test accessible sur Github contenant des vulnérabilités.

Récupération du schéma d’introspection GraphQL

La première étape consiste à récupérer le schéma d’introspection GraphQL. Ce schéma permet d’obtenir des informations importantes sur la structure de GraphQL, notamment les relations entre les différents objets et le nom des différents champs.

Pour ce faire, plusieurs méthodes peuvent être utilisées pour récupérer ce schéma comme l’extension InQL de Burp ou, manuellement via le recours à la requête GraphQL suivante si l’introspection est bien activée.

{__schema{queryType{name}mutationType{name}subscriptionType{name}types{…FullType}directives{name description locations args{…InputValue}}}}fragment FullType on __Type{kind name description fields(includeDeprecated :true){name description args{…InputValue}type{…TypeRef}isDeprecated deprecationReason}inputFields{…InputValue}interfaces{…TypeRef}enumValues(includeDeprecated :true){name description isDeprecated deprecationReason}possibleTypes{…TypeRef}}fragment InputValue on __InputValue{name description type{…TypeRef}defaultValue}fragment TypeRef on __Type{kind name ofType{kind name ofType{kind name ofType{kind name ofType{kind name ofType{kind name ofType{kind name ofType{kind name}}}}}}}}
Récupération du schéma d'introspection GraphQL

Par ailleurs, le schéma peut être importé sur GraphQL Voyager, un outil permettant d’obtenir un graphique interactif du schéma GraphQL.

Import schéma d'introspection sur GraphQL Voyager

Grâce à cet outil, les relations entre les différents objets apparaissent plus clairement et l’exploitation va être beaucoup plus simple à effectuer.

Visualisation des objets du schéma GraphQL

Exploitation des vulnérabilités GraphQL

L’objectif va être d’utiliser toutes les relations afin d’accéder aux différents objets contenant les informations de l’application. Par exemple, accéder aux informations des utilisateurs à partir de la requête qui récupère les notes privées.

Si on clique sur le bouton Private Pastes et qu’on intercepte la requête avec l’outil Burp Suite, on remarque que la requête suivante est transmise au serveur :

query getPastes {
        pastes(public:false) {
          id
          title
          content
          ipAddr
          userAgent
          owner {
            name
          }
          }
        }

En comparant cette requête avec le graphique interactif de GraphQL Voyager, on peut déterminer le chemin parcouru passant par les différentes relations du schéma.

L’attribut __typename peut être ajouté à la requête afin que le serveur retourne le nom de l’objet présent.

En comprenant cette logique, il est possible de récupérer les informations de l’objet users, en passant par la relation users.

query getPastes {
	__typename
  	users {
		username
		password
		__typename
  }
}

Ainsi, le serveur renvoie les informations confidentielles des différents utilisateurs enregistrés sur la plateforme.

Bien entendu, on pourrait aussi passer par le lien search puis UserObject, pour atteindre les informations des utilisateurs :

query getPastes {
	__typename
  	search {
			... on UserObject {
				username
				password
				__typename
			}
			__typename
  }
}

Enfin, de la même façon, la requête suivante permet de récupérer les données de GraphQL :

query getPastes {
	pastes {
		id
		title
		content
		public
		userAgent
		ipAddr
		ownerId
		burn
		owner {
			id
			name
			__typename
		}
		__typename
	}
	search {
		... on UserObject {
			id
			username
			password
			__typename
		}
		__typename
	}
	audits {
		id
		gqloperation
		gqlquery
		timestamp
		__typename
	}
	__typename
}

Cas concret d’une exploitation multi-tenant de GraphQL via une IDOR

Contexte

Lors d’un pentest, nous avons été amenés à tester une application SaaS à architecture multi-tenant, disposant naturellement d’un cloisonnement des données entre différentes entreprises. Et bien évidemment, chacune de ces entreprises disposait de ses propres utilisateurs, rôles et informations confidentielles.

De fait, notre objectif était de vérifier le bon cloisonnement des données entre les différentes entreprises, autrement dit essayer de récupérer des informations auxquelles nous ne sommes pas du tout censés avoir accès. Par conséquent, il s’agissait ici d’un test d’intrusion en boite grise, avec un compte utilisateur « standard » d’une entreprise à notre disposition.

Pour résumer, nous devions d’abord détecter un lien entre notre entreprise et une autre sur la plateforme et trouver des moyens de contourner le cloisonnement en place.

Découverte d’une vulnérabilité IDOR

En déroulant méthodiquement nos tests, nous avons identifié une vulnérabilité IDOR sur une fonctionnalité de l’application. Cette fonctionnalité permettait d’assigner des rôles spécifiques à des projets.

Une IDOR (Insecure Direct Object Reference) est une vulnérabilité de sécurité qui se produit lorsqu’une application web ne contrôle pas correctement les accès aux objets auxquels un utilisateur peut accéder. Cela signifie qu’un utilisateur peut lire, modifier ou supprimer un objet qui ne lui appartient pas, comme des informations sensibles ou des fonctionnalités.

Ainsi, nous avons découvert qu’un utilisateur de notre entreprise était en mesure d’assigner un rôle d’une autre entreprise à un de nos projets, en raison d’un manque de contrôle des droits sur la modification des paramètres d’un projet. Cela a créé un lien entre un projet appartenant à notre entreprise et un rôle appartenant à une autre entreprise.

Exploitation manque de contrôle de droits

Pour exploiter le manque de contrôle des droits dans GraphQL en combinant avec la vulnérabilité IDOR, nous pouvons utiliser GraphQL pour récupérer des informations liées à nos projets, notamment les rôles qui y sont assignés. Ensuite, nous pouvons utiliser ce rôle pour pivoter vers des informations sensibles appartenant à une autre entreprise, en utilisant les faiblesses de contrôle des accès.

Entreprise_Vaadata -> Liste les rôles des projets -> Pivot sur le rôle de l’Entreprise B -> Liste les utilisateurs de l'entreprise B -> Récupère les données appartenant aux utilisateurs

Comment sécuriser GraphQL ?

Pour corriger les problèmes de contrôle des droits sur GraphQL, il est important de mettre en place des mécanismes de sécurité pour s’assurer que seuls les utilisateurs autorisés ont accès aux informations et aux fonctionnalités souhaitées. Il existe plusieurs solutions pour cela.

Tout d’abord, il faut mettre en place un système d’authentification et d’autorisation robuste. Cela signifie que les utilisateurs doivent fournir des informations d’identification valides pour accéder à l’application et que les autorisations sont vérifiées avant de permettre l’accès à des informations ou des fonctionnalités spécifiques.

Ensuite, il est important de mettre en place des contrôles d’accès basés sur les rôles. Cela signifie que les différents rôles ont des autorisations différentes pour accéder à des informations et à des fonctionnalités spécifiques.

Enfin, il est important de mettre en place des contrôles de validation de données pour s’assurer que les utilisateurs ne peuvent pas accéder à des informations ou à des fonctionnalités qui ne leur sont pas destinées en modifiant les paramètres de leurs requêtes.

Auteur : Alexis MARTIN – Pentester @Vaadata