Analyse des SBOM pour les Vulnérabilités de la Chaîne d'Approvisionnement
Quand l'utiliser
- Une nouvelle exigence réglementaire (EO 14028, EU CRA) impose l'analyse SBOM pour les livraisons logicielles
- L'équipe sécurité a besoin d'évaluer les risques tiers en analysant les SBOM fournis par les fournisseurs
- Le pipeline CI/CD nécessite des contrôles de vulnérabilité automatisés sur les SBOM générés
- La réponse aux incidents doit déterminer si une CVE récemment divulguée affecte le logiciel déployé
- L'équipe achats nécessite une évaluation des risques de la chaîne d'approvisionnement pour une acquisition logicielle
Ne pas utiliser pour l'analyse de vulnérabilité en runtime des systèmes en production ; utiliser des outils de scan de conteneurs (Trivy, Grype CLI) ou des scanners de vulnérabilité basés sur l'hôte (Nessus, Qualys) à la place.
Prérequis
- Fichier SBOM au format CycloneDX JSON (v1.4+) ou SPDX JSON (v2.3+)
- Python 3.9+ avec les bibliothèques requests, networkx et packaging installées
- Clé API NVD (gratuite, depuis https://nvd.nist.gov/developers/request-an-api-key) pour des limites de débit plus élevées
- Accès réseau à l'API NVD (https://services.nvd.nist.gov/rest/json/cves/2.0)
- Optionnellement : syft pour la génération SBOM, grype pour la validation croisée
Flux de travail
Étape 1 : Générer le SBOM (s'il n'est pas fourni)
Utilisez syft pour créer un SBOM à partir d'une image conteneur ou d'un répertoire de projet :
# Générer un CycloneDX JSON à partir d'une image conteneur
syft alpine:latest -o cyclonedx-json > sbom-cyclonedx.json
# Générer un SPDX JSON à partir d'un répertoire de projet
syft dir:/chemin/vers/projet -o spdx-json > sbom-spdx.json
# Générer à partir d'un conteneur en cours d'exécution
syft docker:mon-app-conteneur -o cyclonedx-json > sbom.json
Syft prend en charge plus de 30 écosystèmes de paquets, notamment npm, PyPI, Maven, Go modules, apt, apk et RPM. Le SBOM généré inclut les noms de paquets, versions, licences, identifiants CPE et références PURL (Package URL).
Étape 2 : Analyser le SBOM et Extraire les Composants
Analysez le SBOM pour extraire tous les composants logiciels avec leurs identifiants :
Structure CycloneDX JSON :
{
"bomFormat": "CycloneDX",
"specVersion": "1.5",
"components": [
{
"type": "library",
"name": "lodash",
"version": "4.17.20",
"purl": "pkg:npm/[email protected]",
"cpe": "cpe:2.3:a:lodash:lodash:4.17.20:*:*:*:*:*:*:*",
"licenses": [{"license": {"id": "MIT"}}]
}
],
"dependencies": [
{"ref": "pkg:npm/[email protected]", "dependsOn": ["pkg:npm/[email protected]"]}
]
}
Structure SPDX JSON :
{
"spdxVersion": "SPDX-2.3",
"packages": [
{
"name": "lodash",
"versionInfo": "4.17.20",
"externalRefs": [
{"referenceType": "purl", "referenceLocator": "pkg:npm/[email protected]"},
{"referenceType": "cpe23Type", "referenceLocator": "cpe:2.3:a:lodash:lodash:4.17.20:*:*:*:*:*:*:*"}
],
"licenseConcluded": "MIT"
}
],
"relationships": [
{"spdxElementId": "SPDXRef-express", "relatedSpdxElement": "SPDXRef-lodash",
"relationshipType": "DEPENDS_ON"}
]
}
Étape 3 : Corréler les Composants avec la Base de Données NVD CVE
Interrogez l'API NVD 2.0 pour trouver les vulnérabilités connues pour chaque composant :
import requests
NVD_API = "https://services.nvd.nist.gov/rest/json/cves/2.0"
def search_cves_by_cpe(cpe_name, api_key=None):
params = {"cpeName": cpe_name, "resultsPerPage": 50}
headers = {"apiKey": api_key} if api_key else {}
resp = requests.get(NVD_API, params=params, headers=headers, timeout=30)
resp.raise_for_status()
return resp.json().get("vulnerabilities", [])
def search_cves_by_keyword(keyword, version=None, api_key=None):
params = {"keywordSearch": keyword, "resultsPerPage": 50}
headers = {"apiKey": api_key} if api_key else {}
resp = requests.get(NVD_API, params=params, headers=headers, timeout=30)
resp.raise_for_status()
return resp.json().get("vulnerabilities", [])
L'API NVD prend en charge la recherche par nom CPE (la plus précise), mot-clé, ID CVE et plages de dates. Limites de débit : 5 requêtes/30 secondes sans clé API, 50 requêtes/30 secondes avec clé.
Étape 4 : Construire un Graphe de Dépendances et Identifier les Risques Transitifs
Construisez un graphe orienté des dépendances pour tracer la propagation des vulnérabilités :
import networkx as nx
def build_dependency_graph(sbom):
G = nx.DiGraph()
# Ajouter des nœuds pour chaque composant
for comp in sbom["components"]:
G.add_node(comp["purl"], name=comp["name"], version=comp["version"])
# Ajouter des arêtes à partir des relations de dépendance
for dep in sbom.get("dependencies", []):
for child in dep.get("dependsOn", []):
G.add_edge(dep["ref"], child)
return G
L'analyse des dépendances transitives identifie les composants qui ne sont pas inclus directement mais qui sont tirés via des chaînes de dépendances. Une vulnérabilité dans une dépendance transitive profondément imbriquée (par exemple, 4 niveaux de profondeur) représente toujours un risque mais peut être plus difficile à corriger.
Métriques clés du graphe pour l'évaluation des risques :
- Degré entrant : Combien de composants dépendent de celui-ci (degré entrant élevé = rayon d'explosion élevé)
- Chemin le plus court vers la racine : Distance depuis le point d'entrée de l'application (plus proche = plus exploitable)
- Centralité d'intermédiarité : Composants qui se trouvent sur de nombreux chemins de dépendance (risque de goulot d'étranglement)
Étape 5 : Calculer les Scores de Risque
Agrégez les données de vulnérabilité en scores de risque composant et global :
Calcul du Score de Risque :
━━━━━━━━━━━━━━━━━━━━━━
Risque Composant = max(scores CVSS de toutes les CVE affectant le composant)
Risque Pondéré = Risque Composant * Facteur de Dépendance
où Facteur de Dépendance = 1.0 + (0.1 * degré_entrant)
(plus de dépendants = impact organisationnel plus élevé)
Risque Global SBOM = moyenne pondérée de tous les risques composant
pondérée par la centralité de dépendance
Niveaux de Risque :
CRITIQUE : CVSS >= 9.0 ou connu exploité (CISA KEV)
ÉLEVÉ : CVSS >= 7.0
MOYEN : CVSS >= 4.0
FAIBLE : CVSS < 4.0
Étape 6 : Validation Croisée avec Grype
Utilisez grype pour analyser indépendamment le SBOM et comparer les résultats :
# Analyser le SBOM CycloneDX avec grype
grype sbom:sbom-cyclonedx.json -o json > grype-results.json
# Analyser le SBOM SPDX
grype sbom:sbom-spdx.json -o table
# Filtrer par sévérité
grype sbom:sbom-cyclonedx.json --only-fixed --fail-on critical
Grype extrait les données de vulnérabilité de NVD, GitHub Security Advisories, Alpine SecDB, Red Hat, Debian, Ubuntu, Amazon Linux et les bases de données de sécurité Oracle, offrant une couverture plus large que NVD seul.
Étape 7 : Générer un Rapport de Conformité
Produisez un rapport structuré adapté à la conformité réglementaire :
RAPPORT D'ANALYSE DE VULNÉRABILITÉ SBOM
===========================================
Fichier SBOM : app-sbom-cyclonedx.json
Format : CycloneDX v1.5
Date d'analyse : 2026-03-19
Nombre total de composants : 247
Nombre total de dépendances : 1 842 (directes : 34, transitives : 213)
RÉSUMÉ DES VULNÉRABILITÉS
Critique : 3 composants / 5 CVE
Élevé : 11 composants / 18 CVE
Moyen : 27 composants / 41 CVE
Faible : 8 composants / 12 CVE
RÉSULTATS CRITIQUES
1. [email protected]
CVE-2021-23337 (CVSS 7.2) - Injection de commande via template
CVE-2020-28500 (CVSS 5.3) - ReDoS dans trimEnd
Dépendants : 14 composants (rayon d'explosion élevé)
Correctif : Mettre à niveau vers 4.17.21+
2. [email protected]
CVE-2021-44228 (CVSS 10.0) - Log4Shell RCE [CISA KEV]
CVE-2021-45046 (CVSS 9.0) - Contournement de correctif incomplet
Dépendants : 8 composants
Correctif : Mettre à niveau vers 2.17.1+
RISQUES DU GRAPHE DE DÉPENDANCES
Plus dépendant de : [email protected] (47 dépendants)
Chaîne la plus profonde : app -> framework -> adaptateur -> codec -> zlib (5 niveaux)
Composants goulots d'étranglement : 3 composants sur >50% des chemins de dépendance
CONFORMITÉ DES LICENCES
Licences copyleft trouvées : 2 (GPL-3.0 dans libxml2, AGPL-3.0 dans mongodb-driver)
Révision requise pour la distribution commerciale
Concepts Clés
| Terme | Définition |
|---|---|
| SBOM | Software Bill of Materials ; un inventaire formel de tous les composants, bibliothèques et dépendances dans un produit logiciel |
| CycloneDX | Standard SBOM maintenu par OWASP prenant en charge les formats JSON, XML et protobuf avec graphe de dépendances et données de vulnérabilité |
| SPDX | Standard SBOM de la Linux Foundation axé sur la conformité des licences avec prise en charge des détails au niveau paquet, fichier et extrait |
| PURL | Package URL ; un schéma standardisé pour identifier les paquets logiciels entre écosystèmes (par ex., pkg:npm/[email protected]) |
| CPE | Common Platform Enumeration ; Schéma de dénomination NIST pour les produits informatiques utilisé pour corréler avec les données NVD CVE |
| NVD | National Vulnerability Database ; référentiel gouvernemental américain de données de vulnérabilité indexé par identifiants CVE |
| Dépendance Transitive | Une dépendance non déclarée directement mais tirée via la chaîne de dépendances des dépendances directes |
| CISA KEV | Catalogue des vulnérabilités connues exploitées par la CISA ; CVE confirmées comme étant activement exploitées dans la nature |
Outils & Systèmes
- syft (Anchore) : Générateur SBOM open source prenant en charge plus de 30 écosystèmes de paquets et la sortie CycloneDX/SPDX
- grype (Anchore) : Scanner de vulnérabilité qui accepte les SBOM en entrée et corrèle avec plusieurs bases de données d'avis
- cyclonedx-python-lib : Bibliothèque Python pour créer, analyser et valider les SBOM CycloneDX par programmation
- lib4sbom : Bibliothèque Python pour analyser les SBOM aux formats SPDX et CycloneDX
- nvdlib : Enveloppe Python pour l'API NVD 2.0 prenant en charge les requêtes CVE et CPE avec gestion des limites de débit
- OWASP Dependency-Track : Plateforme pour l'analyse continue SBOM, le suivi des vulnérabilités et l'application des politiques
Scénarios Courants
Scénario : Évaluer un Logiciel Fournisseur Après la Divulgation de Log4Shell
Contexte : Après la divulgation de Log4Shell (CVE-2021-44228), l'équipe sécurité doit déterminer quelles applications fournies par les vendeurs contiennent des versions vulnérables de log4j. Plusieurs vendeurs ont fourni des SBOM conformément aux exigences contractuelles.
Approche :
- Collecter tous les SBOM des vendeurs (format JSON CycloneDX ou SPDX)
- Analyser chaque SBOM et rechercher les composants log4j-core avec des versions < 2.17.1
- Interroger l'API NVD pour les CVE spécifiques (CVE-2021-44228, CVE-2021-45046, CVE-2021-45105)
- Construire des graphes de dépendances pour identifier les composants d'application qui dépendent de log4j
- Calculer le rayon d'explosion : combien de services et de points de terminaison sont exposés
- Générer un rapport de correction priorisé trié par exposition et criticité métier
- Valider croisement les résultats avec un scan grype des mêmes SBOM
Pièges :
- Les SBOM des vendeurs peuvent être incomplets, manquant les fichiers JAR ombrés/groupés qui intègrent log4j
- Les différences de version SPDX et CycloneDX peuvent affecter la compatibilité de l'analyseur
- Les limites de débit de l'API NVD peuvent ralentir l'analyse lors du scan de centaines de composants sans clé API
- Les noms CPE dans les SBOM peuvent ne pas correspondre exactement aux entrées NVD, nécessitant une correspondance floue
- Les dépendances transitives peuvent inclure log4j même lorsqu'il n'est pas une dépendance directe