Sécurité

Files.ReadWrite.All : l'exfiltration SharePoint qui ne laisse pas de trace utile

Étude de cas : encadrer une permission Graph qui lit la totalité du SharePoint du tenant.

Équipe GraphWarden·22 avril 2026·9 min de lecture

Le scénario

Samedi 23h. Une application de gestion contractuelle, déployée depuis deux ans dans une firme d'ingénierie de 400 employés, se met à lire SharePoint. Beaucoup lire.

En six heures, 240 Go de données sortent du tenant : contrats clients, rapports d'expertise, dossiers de soumission, devis fournisseurs, correspondance légale. Tout ce qui vit dans les bibliothèques SharePoint, sans distinction.

Lundi matin, l'équipe de sécurité reçoit une alerte Purview DLP : un volume de lectures inhabituel a été détecté. L'attaque est terminée depuis 36 heures. La clé du fournisseur applicatif avait été compromise jeudi. Entre jeudi et samedi, le reconnaissance. Entre samedi et dimanche matin, l'extraction.

Du point de vue de Microsoft Graph, tout était conforme : l'application avait la permission Files.ReadWrite.All, le jeton était valide, les requêtes étaient bien formées. L'audit SharePoint a tout enregistré, et c'est exactement là où les 240 Go étaient déjà partis quand l'alerte est tombée.

Pourquoi Microsoft ne bloque pas ce scénario

Files.ReadWrite.All en permission applicative donne accès à toutes les bibliothèques de tous les sites du tenant. Pas de scoping natif équivalent à Sites.Selected pour cette permission.

Microsoft offre trois couches de défense : les Sensitivity Labels pour le chiffrement au repos, Purview DLP pour la détection de patterns d'exfiltration, et l'audit unifié pour la reconstitution post-incident. Chacune a son rôle, aucune n'est préventive en temps réel sur les appels Graph.

  • Les Sensitivity Labels protègent les fichiers déjà étiquetés. Une bibliothèque mal classée passe au travers.
  • Purview DLP détecte les patterns après un certain volume. L'alerte arrive en minutes, l'extraction en secondes.
  • L'audit unifié est rétrospectif par conception. Il documente, il ne bloque pas.
  • Sites.Selected existe et scope à des sites précis, mais demande une refonte de l'application pour adopter l'API par site, ce que la plupart des ISV ne feront pas.

La gouvernance préventive des appels Graph reste à la charge de l'écosystème. Le même constat que pour Mail.Send : un interrupteur côté Microsoft, pas de pare-feu applicatif.

Ce que l'incident aurait donné avec un périmètre en place

Reprenons le scénario, cette fois avec tous les appels /sites/* et /drives/* routés à travers un proxy de gouvernance. Chaque requête est évaluée avant d'atteindre Graph.

Modèle de base : default-deny. Tout appel qui ne correspond à aucune règle d'allow est bloqué. Les règles suivantes définissent ce à quoi l'application de gestion contractuelle a effectivement besoin d'accéder.

Règle 1 — Quels sites, quelles bibliothèques ?

- name: "Contrats — site scope"
  endpoint_pattern: "/sites/*/drives/*"
  http_methods: [GET]
  conditions:
    all_of:
      - caller_identity:
          application_id: "app-contract-mgmt"
      - object_attribute:
          path: "siteId"
          in: ["site-contracts-active", "site-contracts-archive"]
  action: allow

L'application peut lire deux sites, ceux qui contiennent effectivement les contrats. Les sites RH, finance, direction, projets confidentiels restent inaccessibles, même avec Files.ReadWrite.All accordé côté Graph.

Règle 2 — Débit borné en volume, pas seulement en requêtes

- name: "Contrats — bandwidth ceiling"
  endpoint_pattern: "/sites/*/drives/*/items/*/content"
  conditions:
    all_of:
      - bandwidth_limit:
          max_bytes: 5368709120   # 5 GB
          window_seconds: 86400
          scope: "caller_identity"
  action: allow

La plupart des limitations de débit se font au nombre de requêtes. Pour l'exfiltration, le signal est le volume. 5 Go par jour est largement suffisant pour un usage normal de gestion contractuelle. Au-delà, l'application est coupée avant que les 240 Go ne sortent.

Règle 3 — Types de fichiers autorisés

- name: "Contrats — document types only"
  endpoint_pattern: "/sites/*/drives/*/items/*/content"
  conditions:
    all_of:
      - file_extension:
          in: [".docx", ".pdf", ".xlsx"]
  action: allow

L'application a besoin de contrats et d'annexes, pas d'archives ZIP de 2 Go ni de fichiers .pst. Filtrer les extensions empêche un pattern d'exfiltration classique où l'attaquant archive un site entier avant de l'aspirer.

Règle 4 — Sensitivity Label comme signal bloquant

- name: "Contrats — block confidential labels"
  endpoint_pattern: "/sites/*/drives/*/items/*"
  conditions:
    any_of:
      - object_attribute:
          path: "sensitivityLabel.displayName"
          in: ["Confidential-Legal", "Confidential-HR", "Restricted"]
  action: block

Microsoft Purview pose les étiquettes. GraphWarden les relit avant de servir la requête. Un fichier étiqueté Confidential-HR dans un site que l'application aurait le droit de lire est quand même refusé à la lecture. La défense en profondeur passe de deux couches à trois, appliquées en temps réel.

Règle 5 — Détection d'énumération

- name: "Contrats — enumeration trap"
  endpoint_pattern: "/sites/*/drives/*/items"
  conditions:
    all_of:
      - rate_limit:
          max: 500
          window_seconds: 3600
          scope: "caller_identity"
      - pattern_detect:
          signal: "sequential_pagination"
          threshold: 20
  action: block

Une extraction massive commence toujours par une énumération récursive des bibliothèques. Paginer 20 fois de suite sans accès au contenu est un signal fort. Le blocage préventif coupe la reconnaissance avant que l'extraction ne commence.

Les conditions bandwidth_limit, pattern_detect et file_extension font partie de la grammaire des règles. Voir la documentation pour la liste complète.

Voir la documentation des règles →

Ce que ça change pour le décideur

L'exfiltration SharePoint par une application compromise est le cas où la différence entre détection et prévention se chiffre directement. Purview DLP détecte après coup. Sensitivity Labels protègent les fichiers étiquetés. Ni l'un ni l'autre ne coupe la connexion en cours d'extraction.

Avec une couche de gouvernance devant Graph, trois bascules se produisent.

  1. Le scope effectif se ramène au scope réel. Files.ReadWrite.All reste accordé côté Graph, mais le proxy le ramène aux deux sites que l'application utilise vraiment.
  2. La défense devient synchrone. Un appel refusé ne part pas. Les 240 Go ne quittent pas le tenant, même si la clé est compromise.
  3. L'audit est indépendant du fournisseur. Chaque requête, autorisée ou refusée, génère un événement hors du tenant Microsoft. En cas d'enquête, la preuve n'attend pas la reconstitution des logs SharePoint.

Les limites qu'il faut nommer

La règle site-scope suppose qu'on connaît les sites légitimes. Pour un ISV multi-tenant, la liste doit être maintenue par client et synchronisée avec l'annuaire des sites. Ce travail existait déjà dans toute démarche sérieuse de gouvernance Sensitivity Labels, il est simplement remis à l'avant-plan.

Le filtre sur Sensitivity Label présuppose que les bibliothèques sont étiquetées correctement. Si une bibliothèque contient des documents confidentiels sans étiquette, la règle 4 ne les protège pas. Les règles 1, 2, 3 et 5 restent en revanche effectives, c'est l'intérêt de la défense en profondeur.

Dernière limite : l'application doit passer par le proxy. Si elle conserve ses identifiants Graph en direct, elle contourne la couche. Le modèle de confiance correct fait en sorte que l'application ne détient jamais les secrets Graph réels, uniquement un identifiant de proxy inutilisable ailleurs.

Ce qu'il faut retenir

Files.ReadWrite.All est la permission la plus demandée par les applications qui interagissent avec SharePoint, et celle dont le risque est le plus mal compris. La promesse « nous avons du DLP » est une vérité incomplète : le DLP détecte, il ne bloque pas les appels Graph en temps réel.

Pour une organisation dont les données SharePoint valent quelque chose (firmes professionnelles, institutions financières, santé, secteur public), encadrer cette permission par une couche de gouvernance déclarative ramène un risque non bornable à un risque documenté, auditable, et coupable en quelques minutes.

C'est exactement pour ça que GraphWarden existe.

GraphWarden est développé au Québec, hébergé en région canadienne, et conçu pour les environnements où la conformité Loi 25 et le contrôle applicatif Microsoft Graph sont des exigences non-négociables.