Aller au contenu principal

Moteur de détection des secrets

Philosophie

La détection des secrets est probabiliste : certains secrets sont plus faciles à trouver que d'autres. Il existe un compromis entre peu de fausses alertes et peu d'identifiants manqués (compromis précision / rappel).

Notre moteur de détection des secrets tourne en production depuis 2017, en analysant des milliards de commits provenant de GitHub. Dès le début nous entraînons et évaluons nos algorithmes sur le code open source. Cela a permis à GitGuardian de bâtir un moteur agnostique au langage, capable d'intégrer rapidement de nouveaux secrets ou de nouvelles façons de les déclarer tout en gardant un très faible taux de faux positifs. Nous collectons aussi les retours sur les alertes envoyées, y compris les alertes pro bono :

  • retour explicite lorsqu'un développeur ou une équipe sécurité marque une alerte comme faux positif ;
  • retour implicite lorsqu'un dépôt public est retiré ou qu'un commit public est supprimé peu après notre alerte.

Nous mettons en œuvre deux familles de détecteurs :

  • Détecteurs spécifiques : algorithme dédié à un type de secret (clés AWS, URI Postgres, identifiants SMTP, etc.). Objectif : haut rappel et haute précision pour ce type. Inconvénient : il faut beaucoup de détecteurs spécifiques pour couvrir l'ensemble des secrets existants.

  • Détecteurs génériques : attraper ce que les détecteurs spécifiques manquent, via des motifs génériques comme secret=\{high_entropy_string\} ou password=xxx, email=yyy@corp.com. Cela limite les secrets manqués même si la précision est un peu inférieure à celle des détecteurs spécifiques.

Vous pouvez bien sûr choisir quels détecteurs activer ou désactiver dans nos applications web.

Fonctionnement

Le moteur prend en entrée un Document : une chaîne (patch Git, gist GitHub, message Slack) et un paramètre optionnel : le nom de fichier (secrets.py, index.html, …). Le nom de fichier peut servir en pré-validation : par exemple nous ne analysons pas une image ou une vidéo, où personne ne place de secrets.

Nous appliquons notamment les exclusions suivantes :

  1. Pas d'analyse des fichiers binaires (jpg, tar.*, …).
  2. Certains chemins exclus via des expressions régulières :
node_modules(/|\\)
vendors?(/|\\)
top-1000\.txt$
\.sops$
\.sops\.yaml$
  1. Dans la plupart des cas, nous n'analysons pas les extensions suivantes, sources de nombreux faux positifs et de peu de vrais secrets : ["html", "css", "md", "lock", "storyboard", "xib"]

Principes directeurs du moteur

  • 🎯 Haute précision : limiter les faux positifs pour éviter la fatigue d'alerte.
  • 🔐 Haut rappel : limiter les secrets manqués pour protéger nos clients.
  • Vitesse : moins prioritaire que rappel et précision, mais le moteur est conçu pour analyser l'historique d'un dépôt Git courant en moins d'une minute.
  • 👥 Piloté par la communauté et les clients : amélioration continue grâce aux retours de centaines de milliers de développeurs et de nos clients.

Fonctionnalités principales

Couverture étendue avec plus de 450 détecteurs spécifiques

Nous maintenons une très large bibliothèque de détecteurs spécifiques, couvrant plus de 450 types de secrets différents. Liste exhaustive ici.

Détecter les secrets à plusieurs correspondances et les secrets multi-lignes

GitGuardian prend en charge les secrets à plusieurs correspondances, par exemple OAuth client_id et client_secret, identifiants de base de données, SMTP, etc.

Il prend aussi en charge les secrets multi-lignes, comme les clés privées.

Exemple de clés AWS : la sortie comporte deux correspondances, une pour l'identifiant client et une pour le secret.

input: 'id=AKIAFJKR45SAWSZ5XDF3, client_secret: hjshnk5ex5u34565d4654HJKGjhz545d89sjkjka'
output:
client_id: AKIAFJKR45SAWSZ5XDF3
client_secret: hjshnk5ex5u34565d4654HJKGjhz545d89sjkjka

Exemple d'identifiants de base de données :

input: |
dbusername = admin
dbpassword = 8095uohoiw4ur90
dbhost = db-postgres-nyc1-1111-do-user-111111-0.db.ondigitalocean.com
dbport = 25060
dbdatabase = defaultdb
dbsslmode = require
output:
username: admin
password: 8095uohoiw4ur90
host: db-postgres-nyc1-1111-do-user-111111-0.db.ondigitalocean.com
port: 25060

Déduplication automatique

  • Si deux détecteurs couvrent les mêmes caractères avec les mêmes correspondances, nous écartons la sortie du détecteur qui apporte moins d'informations.

Par exemple slack_token="xoxp-198947049743-7861195093-830655328819-9d40a979cac97bccf1190afb660b37e1" active à la fois le détecteur slack_user_token et un détecteur générique (token=\{high_entropy_string\}). Nous ne conservons que le résultat de slack_user_token pour limiter la fatigue d'alerte et maximiser le contexte utile à la remédiation.

Détecter les secrets encodés en Base64 avec préfixe

Des frameworks récents comme Kubernetes utilisent des secrets encodés en Base64 ; cela devient courant. Nous détectons notamment les secrets préfixés encodés en Base64, comme les clés privées.

Ajouter des insights aux secrets

Nous attachons des insights aux secrets pour aider les analystes AppSec. Exemples :

  • test_file : secret trouvé dans un contexte de test (dossier ou nom de fichier de test).
  • sensitive_file : document dont le nom est considéré comme sensible (.env, credentials.json, …).
  • whitelisted : secret mis sur liste blanche par le développeur.
  • decoded value for encoded secret : valeur décodée jointe à un secret encodé.

Limitations

  1. Nous ne pouvons pas analyser les fichiers binaires (pour l'instant). Certains noms de fichiers binaires peuvent toutefois contenir des secrets (ex. fichiers .pyc en Python).
  2. Par défaut, le nombre de secrets détectés par détecteur et par fichier est plafonné à 8. Pour les détecteurs à haut rappel qui renvoient en général une seule correspondance par document, la limite est portée à 50. Ces seuils limitent la fatigue d'alerte sur des documents bruyants tout en gérant les fichiers légitimement riches en secrets (dizaines de webhooks Slack, etc.). Nous recommandons toujours de relire le document complet lorsqu'un secret est détecté, car d'autres informations sensibles peuvent s'y trouver.

Architecture

Logique générale du moteur :

Les PreValidators éliminent certains noms de fichier sources de faux positifs ou sélectionnent un document selon la présence d'un mot-clé. Par exemple, toute clé SendGrid API doit commencer par SG. : nous pouvons écarter tous les documents sans ce préfixe. Plus d'informations ici.

Le Scanner est une collection de détecteurs qui analyse un Document et produit des candidats Secret.

Les PostValidators valident si les candidats sont de vrais secrets. Chaque Detector a ses propres PostValidators pour équilibrer rappel et précision. Ils filtrent notamment :

  • les clés d'exemple ;
  • les secrets à faible entropie ;
  • les sous-chaînes issues du dictionnaire anglais ;
  • des modèles d'apprentissage automatique pour écarter certains faux secrets selon le contexte.

Liste des PostValidators ici.