Scanner les vulnérabilités de conteneurs avec grype
Mise à jour :
En tant que spécialiste DevOps, je suis constamment à la recherche d’outils innovants pour renforcer la sécurité des applications, en particulier dans l’environnement des conteneurs qui devient de plus en plus omniprésent. Parmi ces outils, Grype se distingue comme une solution robuste et efficace pour l’analyse de vulnérabilités des images de conteneurs.
Grype offre une approche simplifiée, mais, puissante pour identifier et gérer les vulnérabilités au sein des conteneurs. Avec l’augmentation des menaces de sécurité et la complexité croissante des architectures de microservices, l’utilisation d’un outil comme Grype n’est plus une option, mais une nécessité pour assurer la sécurité des déploiements conteneurisés.
Installation de Grype
Sur Linux
L’installation peut se faire avec asdf-vm :
asdf plugin add grypeasdf install grype latestasdf set --home grype latest
Sur Macos
L’installation sur macOS se fait avec brew
:
brew tap anchore/grypebrew install grype
Vérification de l’installation
Pour vérifier que l’installation s’est faite correctement, tapez la commande suivante :
grype --versiongrype 0.73.5
Si tout est ok, vous devriez voir le numéro de version s’afficher.
Utilisation Grype
Grype peut scanner le contenu d’une image de conteneur ou d’un répertoire à la recherche de vulnérabilités.
Il prend en charge les gestionnaires de package et les langages de développement suivant :
- Alpine (apk)
- C (conan)
- C++ (conan)
- Dart (pubs)
- Debian (dpkg)
- Dotnet (deps.json)
- Objective-C (cocoapods)
- Go (go.mod, Go binaries)
- Haskell (cabal, stack)
- Java (jar, ear, war, par, sar)
- JavaScript (npm, yarn)
- Jenkins Plugins (jpi, hpi)
- PHP (composer)
- Python (wheel, egg, poetry, requirements.txt)
- Red Hat (rpm)
- Ruby (gem)
- Rust (cargo.lock)
- Swift (cocoapods)
Recherche de vulnérabilités avec grype
Maintenant, nous pouvons regarder ce que propose grype
. Commençons par le
lancer sur une image de container :
grype dkron/dkron ✔ Vulnerability DB [updated] ✔ Loaded image dkron/dkron:latest ✔ Parsed image sha256:43f45ba9495628b1a66bfdf9bdfde7b85660a46e9975f9fbd9ea737dbf914822 ✔ Scanned for vulnerabilities [8 vulnerability matches] ├── by severity: 2 critical, 1 high, 5 medium, 0 low, 0 negligible └── by status: 5 fixed, 3 not-fixed, 0 ignored[0001] WARN some package(s) are missing CPEs. This may result in missing vulnerabilities. You may autogenerate these using: --add-cpes-if-noneNAME INSTALLED FIXED-IN TYPE VULNERABILITY SEVERITYbusybox 1.34.1-r7 apk CVE-2022-48174 Criticalgithub.com/dgrijalva/jwt-go v3.2.0+incompatible go-module GHSA-w73w-5m7g-f7qc Highgolang.org/x/crypto v0.16.0 0.17.0 go-module GHSA-45x7-px36-x8w8 Mediumk8s.io/client-go v0.18.2 0.18.14 go-module GHSA-8cfg-vx93-jvxw Mediumssl_client 1.34.1-r7 apk CVE-2022-48174 Critical
On retrouve les mêmes que celles remontées par trivy
. Donc plutôt rassurant.
Comme pour trivy
il est possible de l’exécuter sur un répertoire. Par exemple
sur le même dossier que précédemment :
grype dir:./ ✔ Indexed file system . ✔ Vulnerability DB [no update available] ✔ Scanned for vulnerabilities [13 vulnerability matches] ├── by severity: 2 critical, 6 high, 5 medium, 0 low, 0 negligible └── by status: 13 fixed, 0 not-fixed, 0 ignored[0000] WARN no explicit name and version provided for directory source, deriving artifact ID from the given path (which is not ideal)[0006] WARN some package(s) are missing CPEs. This may result in missing vulnerabilities. You may autogenerate these using: --add-cpes-if-noneNAME INSTALLED FIXED-IN TYPE VULNERABILITY SEVERITY@babel/traverse 7.22.20 7.23.2 npm GHSA-67hx-6x53-jw92 Criticalaxios 0.25.0 1.6.0 npm GHSA-wf5p-g6vw-rhxx Mediumgit 1.2.5 1.11.0 gem GHSA-69p6-wvmq-27gg Criticalgit 1.2.5 1.13.0 gem GHSA-pphf-gfrm-v32r Highgit 1.2.5 1.13.0 gem GHSA-pfpr-3463-c6jh Highgot 9.6.0 11.8.5 npm GHSA-pfrx-2q88-qq97 Mediumjson 1.7.4 1.7.7 gem GHSA-x457-cw4h-hq5f Highjson 1.7.4 2.3.0 gem GHSA-jphg-qwrw-7w9g Highpostcss 8.4.30 8.4.31 npm GHSA-7fh5-64p2-3v2j Mediumrake 0.9.2.2 12.3.3 gem GHSA-jppv-gw3r-w3q8 Mediumrdoc 3.12 6.1.2.1 gem GHSA-ggxm-pgc9-g7fp Highrdoc 3.12 3.12.1 gem GHSA-v2r9-c84j-v7xm Mediumtrim 0.0.1 0.0.3 npm GHSA-w5p7-h5w8-2hfq High
Grype prend en argument les sources suivantes :
grype podman:yourrepo/yourimage:tag explicitly use the Podman daemon grype docker:yourrepo/yourimage:tag explicitly use the Docker daemon grype docker-archive:path/to/yourimage.tar use a tarball from disk for archives created from "docker save" grype oci-archive:path/to/yourimage.tar use a tarball from disk for OCI archives (from Podman or otherwise) grype oci-dir:path/to/yourimage read directly from a path on disk for OCI layout directories (from Skopeo or otherwise) grype singularity:path/to/yourimage.sif read directly from a Singularity Image Format (SIF) container on disk grype dir:path/to/yourproject read directly from a path on disk (any directory) grype sbom:path/to/syft.json read Syft JSON from path on disk grype registry:yourrepo/yourimage:tag pull image directly from a registry (no container runtime required) grype purl:path/to/purl/file read a newline separated file of purls from a path on disk
Obtenir des informations sur les vulnérabilités
Grype possède une fonction explain
qui permet d’approfondir la
compréhension des vulnérabilités identifiées lors des scans.
Lorsque vous exécutez la commande explain
, Grype fournit une sortie détaillée,
qui comprend :
- Origine de la Vulnérabilité : D’où vient la vulnérabilité et comment elle a été introduite dans l’image.
- Chemin de Dépendance : Montre comment le paquet vulnérable est lié à d’autres composants de l’image.
- Détails de la Vulnérabilité : Fournit des informations sur la nature de la vulnérabilité, sa sévérité et, si disponible, des liens vers des sources externes pour plus d’informations.
- Recommandations de Correction : Des suggestions sur la manière de résoudre ou de mitiger la vulnérabilité.
Exemple : attention à bien mettre -o json
en sortie de l’analyse
grype dkron/dkron -o json | grype explain --id GHSA-w73w-5m7g-f7qc ✔ Vulnerability DB [no update available] ✔ Loaded image dkron/dkron:latest ✔ Parsed image sha256:43f45ba9495628b1a66bfdf9bdfde7b85660a46e9975f9fbd9ea737dbf914822 ✔ Scanned for vulnerabilities [8 vulnerability matches] ├── by severity: 2 critical, 1 high, 5 medium, 0 low, 0 negligible └── by status: 5 fixed, 3 not-fixed, 0 ignored[0001] WARN some package(s) are missing CPEs. This may result in missing vulnerabilities. You may autogenerate these using: --add-cpes-if-noneGHSA-w73w-5m7g-f7qc from github:language:go (High)Authorization bypass in github.com/dgrijalva/jwt-goRelated vulnerabilities: - nvd:cpe CVE-2020-26160 (High)Matched packages: - Package: github.com/dgrijalva/jwt-go, version: v3.2.0+incompatible PURL: pkg:golang/github.com/dgrijalva/jwt-go@v3.2.0+incompatible Match explanation(s): - github:language:go:GHSA-w73w-5m7g-f7qc Direct match (package name, version, and ecosystem) against github.com/dgrijalva/jwt-go (version v3.2.0+incompatible). Locations: - /usr/local/bin/dkronURLs: - https://github.com/advisories/GHSA-w73w-5m7g-f7qc - https://nvd.nist.gov/vuln/detail/CVE-2020-26160
Choix du format de sortie
Grype peut produire ces types de fichiers :
table
: Un résumé en colonnes (par défaut).cyclonedx
: Un rapport XML conforme à la spécification CycloneDX 1.4 .cyclonedx-json
: Un rapport JSON conforme à la spécification CycloneDX 1.4 .json
: Utilisez-le pour obtenir autant d’informations que possible sur Grype !template
: Permet à l’utilisateur de spécifier le format de sortie.
Fixer le niveau pour produire une erreur
Vous pouvez faire en sorte que Grype se termine avec une erreur si des vulnérabilités sont signalées au niveau ou au-dessus du niveau de gravité spécifié. Cela s’avère pratique lorsque vous utilisez Grype dans un script ou un pipeline CI. Pour ce faire, utilisez l’option suivante :
grype ubuntu:latest --fail-on medium
✔ Vulnerability DB [no update available] ✔ Pulled image ✔ Loaded image ubuntu:latest ✔ Parsed image sha256:174c8c134b2a94b5bb0b37d9a2b6ba0663d82d23ebf62bd51f74a2fd457333da ✘ Scan for vulnerabilities [13 vulnerability matches] ├── by severity: 0 critical, 0 high, 1 medium, 9 low, 3 negligible └── by status: 0 fixed, 13 not-fixed, 0 ignoredNAME INSTALLED FIXED-IN TYPE VULNERABILITY SEVERITYbash 5.1-6ubuntu1 deb CVE-2022-3715 Lowcoreutils 8.32-4.1ubuntu1 deb CVE-2016-2781 Lowgcc-12-base 12.3.0-1ubuntu1~22.04 deb CVE-2022-27943 Lowgpgv 2.2.27-3ubuntu2.1 deb CVE-2022-3219 Lowlibc-bin 2.35-0ubuntu3.5 deb CVE-2016-20013 Negligiblelibc6 2.35-0ubuntu3.5 deb CVE-2016-20013 Negligiblelibgcc-s1 12.3.0-1ubuntu1~22.04 deb CVE-2022-27943 Lowliblzma5 5.2.5-2ubuntu1 deb CVE-2020-22916 Mediumlibpcre3 2:8.39-13ubuntu0.22.04.1 deb CVE-2017-11164 Negligiblelibstdc++6 12.3.0-1ubuntu1~22.04 deb CVE-2022-27943 Lowlibzstd1 1.4.8+dfsg-3build1 deb CVE-2022-4899 Lowlogin 1:4.8.1-2ubuntu2.1 deb CVE-2023-29383 Lowpasswd 1:4.8.1-2ubuntu2.1 deb CVE-2023-29383 Low1 error occurred: * discovered vulnerabilities at or above the severity threshold
Configuration de Grype
Pour configurer grype, on peut utiliser un fichier de configuration. Voici l’ensemble des paramètres que vous pouvez y mettre :
log: # suppress all logging output (env: GRYPE_LOG_QUIET) quiet: false # increase verbosity (-v = info, -vv = debug) (env: GRYPE_LOG_VERBOSITY) verbosity: 0 # explicitly set the logging level (available: [error warn info debug trace]) (env: GRYPE_LOG_LEVEL) level: warn # file path to write logs to (env: GRYPE_LOG_FILE) file: ''
dev: # capture resource profiling data (available: [cpu, mem]) (env: GRYPE_DEV_PROFILE) profile: none
# report output formatter, formats=[json table cyclonedx cyclonedx-json sarif template], deprecated formats=[embedded-cyclonedx-vex-json embedded-cyclonedx-vex-xml] (env: GRYPE_OUTPUT)output: []
# file to write the default report output to (default is STDOUT) (env: GRYPE_FILE)file: ''
# distro to match against in the format: <distro>:<version> (env: GRYPE_DISTRO)distro: ''
# generate CPEs for packages with no CPE data (env: GRYPE_ADD_CPES_IF_NONE)add-cpes-if-none: false
# specify the path to a Go template file (requires 'template' output to be selected) (env: GRYPE_OUTPUT_TEMPLATE_FILE)output-template-file: ''
# (env: GRYPE_CHECK_FOR_APP_UPDATE)check-for-app-update: true
# ignore matches for vulnerabilities that are not fixed (env: GRYPE_ONLY_FIXED)only-fixed: false
# ignore matches for vulnerabilities that are fixed (env: GRYPE_ONLY_NOTFIXED)only-notfixed: false
# ignore matches for vulnerabilities with specified comma separated fix states, options=[fixed not-fixed unknown wont-fix] (env: GRYPE_IGNORE_WONTFIX)ignore-wontfix: ''
# an optional platform specifier for container image sources (e.g. 'linux/arm64', 'linux/arm64/v8', 'arm64', 'linux') (env: GRYPE_PLATFORM)platform: ''
search: # selection of layers to analyze, options=[squashed all-layers] (env: GRYPE_SEARCH_SCOPE) scope: 'squashed' # (env: GRYPE_SEARCH_UNINDEXED_ARCHIVES) unindexed-archives: false # (env: GRYPE_SEARCH_INDEXED_ARCHIVES) indexed-archives: true
ignore: []
# exclude paths from being scanned using a glob expression (env: GRYPE_EXCLUDE)exclude: []
db: # (env: GRYPE_DB_CACHE_DIR) cache-dir: '/home/bob/.cache/grype/db' # (env: GRYPE_DB_UPDATE_URL) update-url: 'https://toolbox-data.anchore.io/grype/databases/listing.json' # (env: GRYPE_DB_CA_CERT) ca-cert: '' # (env: GRYPE_DB_AUTO_UPDATE) auto-update: true # (env: GRYPE_DB_VALIDATE_BY_HASH_ON_START) validate-by-hash-on-start: false # (env: GRYPE_DB_VALIDATE_AGE) validate-age: true # (env: GRYPE_DB_MAX_ALLOWED_BUILT_AGE) max-allowed-built-age: 120h0m0s
external-sources: # (env: GRYPE_EXTERNAL_SOURCES_ENABLE) enable: false maven: # (env: GRYPE_EXTERNAL_SOURCES_MAVEN_SEARCH_MAVEN_UPSTREAM) search-maven-upstream: true # (env: GRYPE_EXTERNAL_SOURCES_MAVEN_BASE_URL) base-url: 'https://search.maven.org/solrsearch/select'
match: java: # (env: GRYPE_MATCH_JAVA_USING_CPES) using-cpes: false dotnet: # (env: GRYPE_MATCH_DOTNET_USING_CPES) using-cpes: false golang: # (env: GRYPE_MATCH_GOLANG_USING_CPES) using-cpes: false # (env: GRYPE_MATCH_GOLANG_ALWAYS_USE_CPE_FOR_STDLIB) always-use-cpe-for-stdlib: true javascript: # (env: GRYPE_MATCH_JAVASCRIPT_USING_CPES) using-cpes: false python: # (env: GRYPE_MATCH_PYTHON_USING_CPES) using-cpes: false ruby: # (env: GRYPE_MATCH_RUBY_USING_CPES) using-cpes: false rust: # (env: GRYPE_MATCH_RUST_USING_CPES) using-cpes: false stock: # (env: GRYPE_MATCH_STOCK_USING_CPES) using-cpes: true
# set the return code to 1 if a vulnerability is found with a severity >= the given severity, options=[negligible low medium high critical] (env: GRYPE_FAIL_ON_SEVERITY)fail-on-severity: ''
registry: # (env: GRYPE_REGISTRY_INSECURE_SKIP_TLS_VERIFY) insecure-skip-tls-verify: false # (env: GRYPE_REGISTRY_INSECURE_USE_HTTP) insecure-use-http: false auth: [] # (env: GRYPE_REGISTRY_CA_CERT) ca-cert: ''
# show suppressed/ignored vulnerabilities in the output (only supported with table output format) (env: GRYPE_SHOW_SUPPRESSED)show-suppressed: false
# orient results by CVE instead of the original vulnerability ID when possible (env: GRYPE_BY_CVE)by-cve: false
# set the name of the target being analyzed (env: GRYPE_NAME)name: ''
# (env: GRYPE_DEFAULT_IMAGE_PULL_SOURCE)default-image-pull-source: ''
# a list of VEX documents to consider when producing scanning results (env: GRYPE_VEX_DOCUMENTS)vex-documents: []
# (env: GRYPE_VEX_ADD)vex-add: []
# delete downloaded databases after diff occurs (env: GRYPE_DELETE)delete: false
# CVE IDs to explain (env: GRYPE_CVE_IDS)cve-ids: []
Lors de son lancement Grype vérifie la présence d’un fichier de configuration correspond à ces chemins :
.grype.yaml
.grype/config.yaml
${HOME}/.grype.yaml
${HOME}/.config/grype/config.yaml
/etc/xdg/grype/config.yaml
Gestion de la DB
Il est utile de vérifier le statut de la base de données de Grype, surtout pour confirmer que les mises à jour ont été correctement appliquées. La commande suivante vous donne des informations sur la version actuelle de la base de données et la date de la dernière mise à jour :
grype db statusLocation: /home/bob/.cache/grype/db/5Built: 2024-01-03 01:26:16 +0000 UTCSchema: 5Checksum: sha256:29fb5bb2796844c92e21ed1753d9b2c4c11cf1a0a905c3e3de4e5b4aad3c71dbStatus: valid
Grype vérifie régulièrement les mises à jour, mais vous pouvez exécuter manuellement cette commande pour vous assurer que vous utilisez les données les plus récentes.
grype db update ✔ Vulnerability DB [no update available]No vulnerability database update available
Intégration Outils CI/CD
L’intégration de Grype dans votre pipeline CI/CD (Continuous Integration/Continuous Deployment) est une étape importante pour automatiser la détection des vulnérabilités dans vos images de conteneurs. Cette intégration assure une évaluation continue et automatique des vulnérabilités, contribuant ainsi à une meilleure sécurité des applications.
Si vous utilisez déjà Trivy, vous pouvez l’intégrer en parralèle.
Conclusion
Grype se distingue par sa simplicité d’utilisation, sa capacité à s’intégrer facilement dans les pipelines CI/CD et sa mise à jour régulière de la base de données de vulnérabilités. Ces caractéristiques en font un outil indispensable pour les consultants DevOps qui souhaitent assurer une surveillance proactive des vulnérabilités.
En conclusion, je recommande fortement d’adopter Grype comme une composante clé de votre arsenal DevOps. Son utilisation régulière et son intégration dans vos processus de développement et de déploiement aideront à garantir que vos applications restent sécurisées et à jour face aux menaces de sécurité émergentes.
Plus d’infos
- Site Officiel : https://anchore.com/grype/ ↗
- Projet Grype : https://github.com/anchore/grype ↗