CVE, SBOM & chaîne d'approvisionnementintermédiaire7 min de lecture

CVE noyau et backports : pourquoi uname -r ne dit rien sur votre niveau de correctifs

Un scanner qui voit 6.8.0 et signale 40 CVE noyau ignore les backports Ubuntu et Debian. Voici comment lire vous-même le changelog de votre paquet noyau, comparer le noyau qui tourne avec celui installé, vérifier les atténuations matérielles dans /sys et décider quand livepatch vaut la peine. Avec les sources gratuites : USN, Debian Security Tracker et le changelog du paquet.

Sommaire
  1. Étape 1 : quel noyau tourne, et lequel est installé ?
  2. Étape 2 : quelles CVE sont corrigées dans mon paquet noyau ?
  3. Étape 3 : que dit la distribution sur les CVE noyau ouvertes ?
  4. Étape 4 : atténuations matérielles — les CVE sans paquet
  5. Étape 5 : quand livepatch vaut la peine
  6. Étape 6 : le rapport hebdomadaire
  7. Pièges
  8. Ce qu'il vous manque encore
  9. Comment monsys fait
  10. FAQ

uname -r donne 6.8.0-45-generic. Un scanner de vulnérabilités voit « 6.8.0 », cherche dans la NVD tout ce qui a été corrigé en 6.8.x, et rapporte quarante CVE. Entre-temps, Ubuntu a rétroporté ces quarante dans 6.8.0-45.45 sans changer le numéro upstream. L'inverse existe aussi : le noyau que vous avez installé est corrigé, mais celui qui tourne est celui d'avant le redémarrage d'il y a trois semaines. Deux questions, donc, et uname -r ne répond à aucune.

Étape 1 : quel noyau tourne, et lequel est installé ?

# En cours d'exécution
uname -r                              # 6.8.0-45-generic
cat /proc/version                     # contient date de build et compilateur — utile pour les builds personnalisés

# Installé (peut être plus récent que celui qui tourne)
dpkg -l 'linux-image-*' | awk '/^ii/{print $2, $3}'
# linux-image-6.8.0-45-generic 6.8.0-45.45
# linux-image-6.8.0-47-generic 6.8.0-47.47   ← plus récent, pas encore démarré
# linux-image-generic          6.8.0-47.47   ← le métapaquet pointe vers le plus récent

# Le système dit-il lui-même qu'un redémarrage est nécessaire ?
cat /var/run/reboot-required 2>/dev/null && cat /var/run/reboot-required.pkgs
# Ou, plus complet (aussi pour les services sur d'anciennes bibliothèques) :
sudo needrestart -b | grep -E 'KSTA|KCUR|KEXP'
# NEEDRESTART-KCUR: 6.8.0-45-generic
# NEEDRESTART-KEXP: 6.8.0-47-generic
# NEEDRESTART-KSTA: 3      ← 1 = ok, 2 = mise à jour ABI-compatible, 3 = redémarrage nécessaire

La variante Debian est identique, avec des versions de style 6.1.0-25-amd64. needrestart est installé par défaut sur les serveurs Ubuntu ; sur Debian : apt install needrestart.

Si KCUR ≠ KEXP, toute analyse CVE du noyau installé est hors sujet : vous faites tourner l'ancien. C'est la première erreur, et la plus courante.

Étape 2 : quelles CVE sont corrigées dans mon paquet noyau ?

L'autorité n'est pas la NVD mais le changelog du paquet que vous faites tourner. Ubuntu et Debian y mentionnent explicitement chaque numéro CVE.

# Ubuntu : le changelog du paquet noyau en cours, toutes les CVE.
# ATTENTION : sur une machine Secure Boot, linux-image-<ver> est le paquet *signé*, et CE
# changelog ne contient que des lignes « Packaging resync » — zéro CVE. Demandez donc le
# changelog du paquet non signé (source : linux), c'est là que sont les correctifs.
apt changelog "linux-image-unsigned-$(uname -r)" 2>/dev/null | grep -oE 'CVE-[0-9]{4}-[0-9]+' | sort -u > /tmp/fixed-in-running.txt
wc -l < /tmp/fixed-in-running.txt      # des centaines sur un noyau LTS vieux d'un an
# Ça donne 0 ? Alors le paquet non signé n'est pas dans votre cache ; linux-modules-<ver> partage la même source :
apt changelog "linux-modules-$(uname -r)" 2>/dev/null | grep -oE 'CVE-[0-9]{4}-[0-9]+' | sort -u > /tmp/fixed-in-running.txt

# Debian : le changelog est local
zcat "/usr/share/doc/linux-image-$(uname -r)/changelog.Debian.gz" | grep -oE 'CVE-[0-9]{4}-[0-9]+' | sort -u > /tmp/fixed-in-running.txt

# Une CVE précise y est-elle ?
grep -q CVE-2024-1086 /tmp/fixed-in-running.txt && echo "corrigée dans le noyau en cours" || echo "NON corrigée (ou non applicable)"

« Pas dans le changelog » ne veut pas automatiquement dire « vulnérable ». La CVE peut concerner un sous-système non compilé dans ce noyau, ou le code vulnérable peut n'avoir été ajouté que dans une version upstream plus récente. Le tracker de la distribution tranche.

Étape 3 : que dit la distribution sur les CVE noyau ouvertes ?

Ubuntu publie un statut par CVE et par version. La source la plus pratique est le flux OSV (le même que dans le guide des paquets OS), avec linux comme paquet source :

. /etc/os-release
# Paquet source du noyau en cours. Les noyaux signés s'appellent "linux-signed[-aws|-azure|…]"
# dans dpkg, mais OSV les connaît comme "linux[-aws|-azure|…]" — d'où le sed.
SRC=$(dpkg-query -W -f='${source:Package}' "linux-image-$(uname -r)" | sed 's/-signed//')
VER=$(dpkg-query -W -f='${source:Version}' "linux-image-$(uname -r)")
echo "$SRC $VER"                       # linux 6.8.0-45.45
curl -s -X POST https://api.osv.dev/v1/query -H 'Content-Type: application/json' \
  -d "{\"package\":{\"name\":\"$SRC\",\"ecosystem\":\"Ubuntu:$VERSION_ID\"},\"version\":\"$VER\"}" \
  | jq -r '.vulns[]? | .id' | sort -u > /tmp/open-kernel.txt
wc -l < /tmp/open-kernel.txt

C'est la liste des CVE pour lesquelles Ubuntu considère votre version exacte de noyau comme vulnérable — après prise en compte de tous les backports. Sur un noyau mis à jour ce mois-ci : généralement quelques dizaines de « medium/low » sur lesquelles Ubuntu travaille encore ou marquées deferred. Sur un noyau vieux de six mois : des centaines.

Debian a le Security Tracker avec un export JSON. Il est gros (des dizaines de Mo) mais complet :

curl -s https://security-tracker.debian.org/tracker/data/json -o /tmp/debsec.json
jq -r --arg rel "$VERSION_CODENAME" '
  .linux | to_entries[]
  | select(.value.releases[$rel].status == "open")
  | [.key, .value.releases[$rel].urgency, (.value.description // "")[0:80]] | @tsv' /tmp/debsec.json \
  | sort | column -t -s $'\t' | head -30

La colonne urgency (unimportant, low, medium, high) est l'évaluation propre de Debian ; unimportant signifie généralement « n'affecte pas le build Debian ».

Étape 4 : atténuations matérielles — les CVE sans paquet

Spectre, Meltdown, MDS, Retbleed, Downfall, Zenbleed : ce sont des CVE dans le CPU, atténuées par le noyau et le microcode. Que votre machine soit protégée ne se lit pas dans un changelog mais dans /sys :

grep -H . /sys/devices/system/cpu/vulnerabilities/* | sed 's|.*/vulnerabilities/||'
# spectre_v2:Mitigation: Enhanced / Automatic IBRS; IBPB: conditional; RSB filling; ...
# mds:Not affected
# gather_data_sampling:Vulnerable: No microcode      ← c'est ça que vous cherchez
# retbleed:Mitigation: Enhanced IBRS

Tout ce qui dit Vulnerable est un point ouvert. Le correctif est généralement du microcode (apt install intel-microcode ou amd64-microcode, puis redémarrage) — sur un VPS, seul l'hébergeur peut le faire, et c'est alors une question à l'hébergeur, pas une action sur le serveur. Incluez la sortie dans vos preuves ; un auditeur qui demande « Spectre » reçoit ainsi une réponse factuelle.

Étape 5 : quand livepatch vaut la peine

Livepatch (Ubuntu Pro / canonical-livepatch, ou kpatch sur RHEL) corrige les CVE noyau critiques en mémoire, sans redémarrage. Il ne couvre que les CVE que Canonical juge high/critical et qui sont livepatchables — donc pas tout.

# Ubuntu Pro est gratuit pour 5 machines (compte personnel)
sudo pro attach <token>
sudo pro enable livepatch
canonical-livepatch status --verbose
# ...
#   patchState: applied
#   fixes: CVE-2024-xxxx, CVE-2024-yyyy

L'arbitrage est simple : livepatch achète du temps entre « CVE publiée » et « fenêtre de redémarrage planifiée ». Il ne remplace pas le redémarrage ; needrestart continue de signaler KSTA 3 jusqu'à ce que vous redémarriez vraiment. Pour un serveur que vous redémarrez de toute façon chaque mois dans une fenêtre de maintenance, livepatch est surtout utile pour la rare critical exploitée dès le jour 0. Pour une base de données qui ne peut s'arrêter que deux fois par an, c'est essentiel.

Étape 6 : le rapport hebdomadaire

Tout ensemble dans un script qui produit une ligne par serveur :

sudo tee /usr/local/sbin/kernel-status.sh >/dev/null <<'EOF'
#!/usr/bin/env bash
. /etc/os-release
RUN=$(uname -r)
INST=$(dpkg -l 'linux-image-[0-9]*' | awk '/^ii/{print $2}' | sed 's/linux-image-//' | sort -V | tail -1)
KSTA=$(needrestart -b 2>/dev/null | awk -F': ' '/KSTA/{print $2}')
VULN=$(grep -l -E '^Vulnerable' /sys/devices/system/cpu/vulnerabilities/* 2>/dev/null | xargs -rn1 basename | paste -sd, -)
SRC=$(dpkg-query -W -f='${source:Package}' "linux-image-$RUN" 2>/dev/null | sed 's/-signed//')
VER=$(dpkg-query -W -f='${source:Version}' "linux-image-$RUN" 2>/dev/null)
OPEN=$(curl -s -m 20 -X POST https://api.osv.dev/v1/query -H 'Content-Type: application/json' \
  -d "{\"package\":{\"name\":\"${SRC:-linux}\",\"ecosystem\":\"Ubuntu:$VERSION_ID\"},\"version\":\"$VER\"}" \
  | jq -r '.vulns // [] | length')
printf 'host=%s running=%s installed=%s reboot_state=%s cpu_vulnerable=%s open_kernel_cves=%s\n' \
  "$(hostname -s)" "$RUN" "$INST" "${KSTA:-?}" "${VULN:--}" "${OPEN:-?}"
EOF
sudo chmod 0755 /usr/local/sbin/kernel-status.sh
sudo /usr/local/sbin/kernel-status.sh
# host=web-01 running=6.8.0-45-generic installed=6.8.0-47-generic reboot_state=3 cpu_vulnerable=gather_data_sampling open_kernel_cves=23

Cette ligne par hôte, chaque semaine dans un fichier ou vers ntfy, répond aux deux questions de l'introduction : est-ce que je fais tourner ce que j'ai installé, et combien reste-t-il d'ouvert pour ce que je fais tourner.

Pièges

  • Noyaux cloud et signés. -aws, -azure, -gcp, -kvm sont des paquets source distincts (linux-aws, …) avec leurs propres changelogs et USN. Et sur toute machine avec Secure Boot, le paquet source dans dpkg s'appelle linux-signed (ou linux-signed-aws), alors qu'OSV et les USN utilisent linux. Demandez toujours le paquet source à dpkg et retirez -signed ; linux codé en dur est faux sur AWS, linux-signed codé en dur renvoie zéro résultat.
  • Noyaux personnalisés et de fournisseurs. Un noyau d'hébergeur (5.15.0-hoster1) ou compilé maison (6.9.0-custom) n'a ni changelog avec CVE ni entrée dans le tracker. /proc/version sans buildd@ est l'indice. Traitez ces noyaux comme « niveau de correctifs inconnu », ce qui en audit équivaut à « vulnérable ».
  • Le changelog du mauvais paquet. apt changelog linux-image-$(uname -r) sur une machine Secure Boot renvoie le changelog de linux-signed, qui ne contient aucune CVE. Vous concluriez « rien de corrigé » alors qu'il y en a 200. Utilisez linux-image-unsigned-… ou linux-modules-….
  • /boot plein. Chaque noyau prend 100–150 Mo. Si /boot est plein, l'installation du nouveau noyau échoue à mi-chemin et vous continuez silencieusement sur l'ancien. apt autoremove --purge nettoie ; gardez-en toujours deux.
  • Les scanners qui comparent des numéros de version. Si vous faites tourner Nessus, OpenVAS ou Trivy sur les hôtes, filtrez les CVE noyau de leur rapport et utilisez le tracker de la distribution. Sinon, vous débattez chaque mois de quarante faux positifs.
  • reboot-required n'est pas un signal noyau uniquement. /var/run/reboot-required apparaît aussi pour glibc, systemd et dbus. Le fichier .pkgs dit lesquels.

Ce qu'il vous manque encore

  • La vue d'ensemble de la flotte. « Quels hôtes font tourner un noyau avec une CVE KEV ouverte ? » est un for h in $(cat hosts); do ssh $h kernel-status.sh; done — puis la liste KEV à côté.
  • L'orchestration des redémarrages. Savoir que 14 serveurs doivent redémarrer est l'étape un ; les redémarrer dans le bon ordre, dans la bonne fenêtre, avec un plan de retour arrière, c'est le vrai travail. Voir le guide sur les mises à jour du noyau en production.
  • La preuve datée. Pour NIS2 et ISO 27001 A.8.8, vous voulez montrer : CVE publiée le X, noyau installé le Y, redémarré le Z. Ce sont trois horodatages actuellement dans trois logs différents.

Comment monsys fait

L'agent monsys rapporte le noyau en cours, les noyaux installés, reboot_required, is_custom_build et les modules chargés. Le pipeline CVE noyau du hub les confronte aux USN Ubuntu, au Debian Security Tracker, à RHEL CSAF et aux GLSA Gentoo — en tenant compte des backports, par paquet source (y compris linux-aws et consorts). Les CVE noyau ouvertes sont enrichies avec EPSS et KEV et pondérées dans le Trust Score. Les mises à jour du noyau se planifient par lots avec des fenêtres de redémarrage, où le demandeur et l'approbateur doivent être des personnes différentes (séparation des tâches) — et chaque étape est journalisée avec signature.

FAQ

Mon scanner dit que le noyau 6.8.0 a quarante CVE. Est-ce exact ?

Presque certainement pas. Ubuntu et Debian rétroportent les correctifs sans changer le numéro de version upstream. Vérifiez le changelog de votre paquet noyau (apt changelog linux-image-unsigned-$(uname -r)) ou le flux OSV avec votre version exacte de paquet ; eux connaissent les backports.

Dois-je redémarrer après chaque mise à jour du noyau ?

Oui, pour faire tourner le nouveau noyau. Sans redémarrage, le noyau corrigé est sur le disque tandis que l'ancien continue en mémoire. Livepatch est l'exception pour un ensemble limité de CVE critiques, mais même alors un redémarrage finit par être nécessaire.

Livepatch Ubuntu Pro est-il gratuit ?

Pour au maximum cinq machines avec un compte Ubuntu One personnel, oui. Au-delà, c'est un abonnement payant. Debian n'a pas d'équivalent livepatch officiel ; là, une fenêtre de redémarrage planifiée est la pratique.

Rédigé par l'équipe monsys — des sysadmins qui font cela tous les jours.

Fait à la main ? Laissez monsys s'en charger en continu.

Tout ce que contient ce guide tourne dans monsys comme contrôle permanent, avec historique, alertes et preuves d'audit. 5 serveurs gratuits, hébergés en Belgique, installés en 60 secondes.