Automatiser la détection de vulnérabilités 🕵️
Selon une étude de Synopsys près de 60% des codebases des entreprises contiennent au moins une vulnérabilité provenant de bibliothèques open source. Le problème ne tient pas au fait d’utiliser des bibliothèques open-source, il est d’ailleurs difficile de s’en passer aujourd’hui. Le problème vient principalement d’un manque d’analyse et de surveillance des différentes bibliothèques utilisées pour développer ces applications.
Si vous hébergez le code d’un de vos projets personnels sur GitHub, il y a de fortes chances que vous ayez reçu une alerte de vulnérabilité de sécurité à un moment donné. Ces alertes sont également affichées sur l’interface web de GitHub.
Malheureusement en entreprise le code source n’est pas toujours hébergé sur GitHub et par conséquent cette fonctionnalité ne peut pas être exploitée. Heureusement il est possible d’automatiser cette analyse en utilisant Jenkins et Maven.
Deux paramètres en entrée
La détection de vulnérabilités connues repose sur deux paramètres d’entrée : un inventaires de toutes les bibliothèques dont dépendent votre projet et une liste des vulnérabilités connues dans les bibliothèques open-source.
Dans l’exemple de cet article l’inventaire est contenu dans le fichier POM du projet Maven.
La liste des vulnérabilités est quant elle fournie par une agence Américaine, le NIST (National Institute of Standards and Technology). Cette liste nommée la National Vulnerability Database (NVD) supporte la plupart des langages modernes.
Un exemple concret
La théorie c’est bien, mais rien ne remplace la pratique !
Je vous propose de repartir du pipeline que j’ai présenté dans mon précédent article.
Nous allons forcer un retour à une précédente révision qui contient des vulnérabilités.
Pour faire cela nous allons rajouter la ligne suivante juste après le checkout Git :
sh 'git reset --hard b4c1728fe143548a6c72f6084eb20c1fe67a98cf'
Ensuite nous allons rajouter une étape supplémentaire dans le pipeline afin de détecter les vulnérabilités :
stage('Vulnerabilities') {
steps {
sh "mvn org.owasp:dependency-check-maven:aggregate -Dformat=xml"
}
}
Vous pouvez maintenant relancer votre pipeline.
Après quelques minutes vous devriez voir ceci :
L’étape “Vulnerabilities” va prendre entre 5 et 20 minutes.
En effet lors de la première exécution, la base de données NVD va être téléchargée.
Vous pouvez vérifier cela dans les logs du pipeline :
[INFO] Checking for updates
[INFO] NVD CVE requires several updates; this could take a couple of minutes.
[INFO] Download Started for NVD CVE - 2003
[INFO] Download Complete for NVD CVE - 2003 (1637 ms)
[INFO] Processing Started for NVD CVE - 2003
[...]
[INFO] Processing Started for NVD CVE - 2020
[INFO] Processing Complete for NVD CVE - 2020 (420 ms)
[INFO] Download Started for NVD CVE - Modified
[INFO] Download Complete for NVD CVE - Modified (2087 ms)
[INFO] Processing Started for NVD CVE - Modified
[INFO] Processing Complete for NVD CVE - Modified (7716 ms)
[INFO] Begin database maintenance
[INFO] Updated the CPE ecosystem on 51316 NVD records
[INFO] End database maintenance (26827 ms)
[INFO] Begin database defrag
[INFO] End database defrag (26153 ms)
[INFO] Check for updates complete (296989 ms)
Afficher le résultat
Pour l’instant le résultat de l’analyse est affiché uniquement dans les logs du pipeline :
[INFO] Analysis Started
[INFO] Finished Archive Analyzer (0 seconds)
[INFO] Finished File Name Analyzer (0 seconds)
[INFO] Finished Jar Analyzer (0 seconds)
[INFO] Finished Dependency Merging Analyzer (0 seconds)
[INFO] Finished Version Filter Analyzer (0 seconds)
[INFO] Finished Hint Analyzer (0 seconds)
[INFO] Created CPE Index (3 seconds)
[INFO] Finished CPE Analyzer (4 seconds)
[INFO] Finished False Positive Analyzer (0 seconds)
[INFO] Finished NVD CVE Analyzer (0 seconds)
[INFO] Finished Sonatype OSS Index Analyzer (1 seconds)
[INFO] Finished Vulnerability Suppression Analyzer (0 seconds)
[INFO] Finished Dependency Bundling Analyzer (0 seconds)
[INFO] Analysis Complete (6 seconds)
[WARNING]
One or more dependencies were identified with known vulnerabilities in boucles:
pdfbox-1.8.10.jar (pkg:maven/org.apache.pdfbox/pdfbox@1.8.10, cpe:2.3:a:apache:pdfbox:1.8.10:*:*:*:*:*:*:*) : CVE-2016-2175, CVE-2018-11797, CVE-2018-8036
jempbox-1.8.10.jar (pkg:maven/org.apache.pdfbox/jempbox@1.8.10, cpe:2.3:a:apache:pdfbox:1.8.10:*:*:*:*:*:*:*) : CVE-2016-2175, CVE-2018-11797, CVE-2018-8036
See the dependency-check report for more details.
Il serait bien plus pratique de pouvoir afficher les résultats avec un joli graph et proposer des options de tri.
Pour cela il va nous falloir installer un nouveau plugin sur le serveur Jenkins.
Voici comment installer le plugin OWASP Dependency-Check :
Une fois le plugin installé, nous allons rajouter une instruction dans le pipeline :
post {
success {
step([$class: 'DependencyCheckPublisher'])
}
}
Vous pouvez alors exécuter de nouveau le pipeline et vous devriez voir ceci :
En cliquant sur le graph “Dependency-Check Trend” vous pouvez consulter le détail des vulnérabilités :
Définir des seuils d’alerte
Ce qui serait vraiment chouette ça serait d’être alerté quand une nouvelle vulnérabilité est découverte. Figurez-vous que c’est possible !
Pour ce faire il est possible d’utiliser les paramètres du plugin, comme par exemple “unstableTotalHigh”. Nous allons modifier le script du pipeline en conséquent :
step([$class: 'DependencyCheckPublisher', unstableTotalHigh: 1])
Une fois le pipeline relancé nous constatons qu’il est maintenant à l’état instable :
Un rapide coup d’oeil au fichier de log permet de vérifier la raison de cet état :
Post stage
[Pipeline] dependencyCheckPublisher
[DependencyCheck] Collecting Dependency-Check artifact
[DependencyCheck] Findings exceed configured thresholds
La liste des paramètres possibles est disponible sur la documentation en ligne.
Courage et prudence
La tentation serait grande maintenant de mettre à jour toutes les dépendances qui posent problème. Ce n’est pas forcément une mauvaise idée mais ce n’est pas non plus automatiquement une bonne idée.
La première question à vous poser est de savoir si la vulnérabilité est exploitable dans votre logiciel. Il est possible par exemple que seule une fonctionnalité très précise soit concernée et par conséquent si votre application ne l’utilise pas vous êtes relativement serein. Un première phase d’analyse est donc bienvenue.
Ensuite il faut aussi considérer la solidité de votre filet de sécurité. Pardon ? Je veux parler de vos suites de tests et de votre manière de déployer. Si vous effectuez uniquement des test manuels et que vous déployez tous les six mois votre filet est très faible. A contrario si vous avez plusieurs suites de tests automatisées (unitaires, fonctionnels, de charge, d’intégration) et que vous déployez quotidiennement en utilisant une stratégie canary avec des rollbacks automatiques votre filet est bien costaud. A vous donc de jauger la confiance que vous avez en vos tests et le temps que cela va vous prendre pour effectuer une analyse de non régression.
Pour aller plus loin
Si vous souhaitez approfondir le sujet je vous conseille les liens suivants :
- https://github.blog/2019-12-11-behind-the-scenes-github-vulnerability-alerts/
- https://blog.cloudflare.com/javascript-libraries-are-almost-never-updated/
D’autre part OWASP est un outil open-source gratuit et relativement simple, il existe des outils plus complet sur le marché tel Black Duck (édité par Synopsys).
Je souhaite aussi attirer votre attention sur le fait qu’il se passe en moyenne sept jours entre le moment où une vulnérabilité est découverte et le moment où elle est partagée dans la base NVD. L’utilisation d’un tel outil ne vous dispense donc pas de faire une veille de sécurité.
J’espère que cet article vous a plu !
Le script complet du pipeline d’aujourd’hui est disponible sur GitHub : https://gist.github.com/jbleduigou/b0e4a9ad180045a93a52b36308046e7a
N’hésitez pas à me faire part de vos commentaires ou questions en bas de cet article ou en m’envoyant un message sur LinkedIn :
http://www.linkedin.com/in/jbleduigou/en.
Photo de couverture par Luke Chesser.
Cet article a initialement été publié sur Medium.