Scanner de vulnérabilités basé sur shell pour CVE-2026-45185 (Dead.Letter) dans Exim MTA. Détecte une use-after-free dans les builds GnuTLS, vérifie la version, la bibliothèque TLS et la configuration CHUNKING. Produit une sortie JSON pour l'intégration CI/CD.
Un script shell pour détecter si un système Linux est vulnérable à CVE-2026-45185, une utilisation après libération (use-after-free) dans l'agent de transfert de courrier Exim qui peut conduire à une exécution de code à distance.
Conçu pour être utilisé dans les pipelines CI/CD, les outils de gestion de configuration et les audits système ad-hoc. Produit une sortie à la fois lisible par l'homme et lisible par machine (JSON).
CVE-2026-45185 (alias : Dead.Letter) est un bogue d'utilisation après libération (use-after-free) dans l'analyse du corps des messages BDAT (données binaires) d'Exim, déclenché lorsque TLS est géré par GnuTLS.
Lors de l'arrêt de TLS, Exim libère son tampon de transfert TLS — mais un wrapper de réception BDAT imbriqué peut toujours traiter des octets entrants et appeler ungetc(), écrivant un seul octet \n dans la région libérée. Cette écriture d'un octet corrompt les métadonnées de l'allocateur du tas (heap), à partir desquelles un attaquant peut obtenir davantage de primitives mémoire et réaliser une exécution de code à distance.
| Propriété | Détail |
|---|
| CVE | CVE-2026-45185 |
| Alias | Dead.Letter |
| Type | Use-After-Free (CWE-416) |
| Composant | Gestionnaire BDAT/CHUNKING d'Exim (builds GnuTLS uniquement) |
| Vecteur d'attaque | Réseau — non authentifié, nécessite seulement une connexion TLS et l'extension CHUNKING |
| Versions affectées | Exim 4.97 – 4.99.2, builds GnuTLS uniquement |
| Corrigé dans | Exim 4.99.3 |
| Découvert par | Federico Kirschbaum, XBOW Security Lab (signalé le 1er mai 2026) |
Les builds OpenSSL ne sont pas concernés. La vulnérabilité est spécifique à Exim compilé avec
USE_GNUTLS=yes. Si votre Exim est lié à OpenSSL, vous n'êtes pas vulnérable quelle que soit la version.
Le script fonctionne via un arbre de décision, s'arrêtant et marquant le système non vulnérable dès qu'une condition de sécurité définitive est confirmée :
Vérification 1 — Présence d'Exim
Recherche dans $PATH et les emplacements d'installation courants (/usr/sbin/exim, /usr/sbin/exim4, /usr/local/sbin/exim). Si Exim n'est pas trouvé, le système n'est pas vulnérable et le script se termine immédiatement.
Vérification 2 — Version d'Exim
Analyse la sortie de exim -bV et la compare à la plage affectée (4.97 – 4.99.2). Les versions ≥ 4.99.3 sont considérées comme corrigées. Les versions en dehors de la plage connue sont marquées non vulnérables (avec une note si elles ne sont pas reconnues).
Vérification 3 — Bibliothèque TLS (le point critique) Utilise trois méthodes de détection en séquence :
exim -bV (la plus fiable — Exim rapporte ses propres fonctionnalités de compilation, ex. Support for: GnuTLS)lddstrings (solution de repli)Si OpenSSL est détecté → le verdict passe à non vulnérable quelle que soit la version. Si GnuTLS est détecté → la surface d'attaque est confirmée comme présente. Si aucun des deux ne peut être déterminé → le résultat est inconcluant.
Vérification 4 — Configuration CHUNKING/BDAT (vérification du contournement)
Ne s'exécute que si le système est toujours marqué vulnérable à ce stade. Vérifie si chunking_advertise_hosts a été explicitement défini à une valeur vide dans la configuration d'Exim, ce qui désactive l'annonce BDAT et bloque le vecteur d'attaque. Gère à la fois les configurations mono-fichier et la disposition split-config de Debian (fragments /etc/exim4/conf.d/).
Note : si
chunking_advertise_hostsest absent de la configuration (comportement par défaut), Exim annonce CHUNKING à tous les hôtes (*). L'option doit être explicitement définie à une valeur vide pour la désactiver.
Vérification 5 — Atténuations système informatives Ne modifie pas le verdict, mais rapporte les facteurs qui affectent l'exploitabilité :
/proc/sys/kernel/randomize_va_space) — doit être 2checksec pour le binaire Exim (PIE, RELRO, canaris de pile) si checksec est installéMemoryDenyWriteExecute, NoNewPrivileges, SystemCallFilter/proc (pour la vérification ASLR)grep, awk, ldd, headchecksec (optionnel — pour l'analyse du durcissement du binaire)systemctl (optionnel — pour l'inspection de l'unité systemd)Debian-exim sur Debian/Ubuntu)Aucune dépendance externe n'est requise pour les vérifications de vulnérabilité de base.
chmod +x check_cve_2026_45185.sh
./check_cve_2026_45185.sh
| Option | Description |
|---|---|
--json | Sortie des résultats sous forme d'objet JSON (voir ci-dessous) |
--quiet | Supprime toute sortie ; seul le code de sortie est défini |
--no-color | Désactive les codes couleur ANSI (utile pour les fichiers journaux) |
--help / -h | Affiche les informations d'utilisation |
| Code | Signification |
|---|---|
0 | Non vulnérable (ou une condition de sécurité définitive a été trouvée) |
1 | Vulnérable |
2 | Inconcluant — impossible de déterminer un ou plusieurs faits requis ; à traiter comme potentiellement vulnérable |
3 | Erreur de script ou environnement non pris en charge |
CVE-2026-45185 (Dead.Letter) — Exim Vulnerability Assessment
============================================================
[CHECK] Checking for Exim installation...
[WARN] Exim binary found: /usr/sbin/exim4
[CHECK] Checking Exim version...
Detected version: 4.99.1
[FAIL] Exim 4.99.1 is in the vulnerable range (4.97 – 4.99.2).
[CHECK] Checking TLS library linkage (GnuTLS vs OpenSSL)...
[FAIL] Exim is linked against GnuTLS — this build IS affected.
[CHECK] Checking CHUNKING (BDAT) advertisement config...
Config file: /etc/exim4/exim4.conf
[WARN] chunking_advertise_hosts is not disabled — BDAT is active (default advertises to all hosts).
Tip: add 'chunking_advertise_hosts =' (empty value) to your main config to disable BDAT as a workaround.
[CHECK] Checking system-level exploit mitigations (informational)...
[PASS] ASLR: full randomisation (randomize_va_space=2)
glibc version: 2.35 (2.32+ has stronger heap metadata checks)
[WARN] systemd: MemoryDenyWriteExecute not set — recommend adding to unit
[WARN] systemd: NoNewPrivileges not set
------------------------------------------------------------
VERDICT
------------------------------------------------------------
VULNERABLE — CVE-2026-45185
Reason: Exim version 4.99.1 is in vulnerable range 4.97–4.99.2
Recommended actions:
1. Upgrade Exim to 4.99.3 or later (primary fix)
2. As a workaround, set 'chunking_advertise_hosts =' (empty) in exim config
3. Add MemoryDenyWriteExecute=yes and NoNewPrivileges=yes to the systemd unit
4. Ensure ASLR is set to 2: echo 2 > /proc/sys/kernel/randomize_va_space
------------------------------------------------------------
--json){
"cve": "CVE-2026-45185",
"alias": "Dead.Letter",
"host": "mailserver-01",
"timestamp": "2026-05-12T17:00:00Z",
"verdict": "vulnerable",
"reason": "Exim version 4.99.1 is in vulnerable range 4.97–4.99.2",
"exit_code": 1,
"findings": {
"exim_binary": "/usr/sbin/exim4",
"exim_version": "4.99.1",
"exim_version_vulnerable": "true",
"tls_library": "gnutls",
"tls_library_detected": "gnutls",
"exim_config": "/etc/exim4/exim4.conf",
"chunking_advertised": "true",
"aslr_level": "2",
"glibc_version": "2.35"
},
"mitigations": [
"aslr=full"
]
}
- name: Check for CVE-2026-45185
run: |
chmod +x check_cve_2026_45185.sh
./check_cve_2026_45185.sh --json | tee vuln-report.json
exit $(jq '.exit_code' vuln-report.json)
- name: Upload vulnerability report
if: always()
uses: actions/upload-artifact@v4
with:
name: cve-2026-45185-report
path: vuln-report.json
check-exim-vuln:
stage: security
script:
- chmod +x check_cve_2026_45185.sh
- ./check_cve_2026_45185.sh --json > vuln-report.json
artifacts:
when: always
paths:
- vuln-report.json
allow_failure: false
- name: Run CVE-2026-45185 check
script: check_cve_2026_45185.sh --json
register: vuln_check
failed_when: vuln_check.rc == 1
changed_when: false
- name: Show vulnerability report
debug:
msg: "{{ vuln_check.stdout | from_json }}"
# Get just the verdict
./check_cve_2026_45185.sh --json | jq -r '.verdict'
# Check if a specific mitigation was found
./check_cve_2026_45185.sh --json | jq '.mitigations | contains(["aslr=full"])'
# Run across multiple hosts and collect results
for host in mail1 mail2 mail3; do
ssh "$host" 'bash -s' < check_cve_2026_45185.sh --json
done | jq -s '.'
# Debian / Ubuntu
apt-get update && apt-get install --only-upgrade exim4
# RHEL / CentOS / Fedora
dnf upgrade exim
# From source
# Download 4.99.3 from https://ftp.exim.org/pub/exim/exim4/
# and rebuild with your existing Local/Makefile settings
Vérifier après la mise à niveau :
exim -bV | head -1
# Expected: Exim version 4.99.3 ...
Si vous ne pouvez pas mettre à jour immédiatement, ajoutez la ligne suivante dans la section de configuration principale de votre configuration Exim pour désactiver complètement l'annonce BDAT, bloquant ainsi le vecteur d'attaque :
chunking_advertise_hosts =
La valeur vide signifie « aucun hôte » — Exim n'annoncera plus l'extension CHUNKING dans les réponses EHLO. Redémarrez Exim après avoir effectué cette modification :
# Debian / Ubuntu
systemctl restart exim4
# Other systemd systems
systemctl restart exim
Vérifier que CHUNKING n'est plus annoncé :
# Connect and check the EHLO response — CHUNKING should not appear
echo QUIT | openssl s_client -connect localhost:25 -starttls smtp 2>/dev/null \
| grep -i chunking
# No output = CHUNKING is disabled
Ceci est un contournement, pas une correction. Certains serveurs de messagerie expéditeurs utilisent BDAT pour la livraison de messages volumineux. Sa désactivation peut entraîner des problèmes de compatibilité avec ces expéditeurs. Mettez à niveau vers la version 4.99.3 dès que possible.
Même sur un système corrigé, l'ajout de ces directives à l'unité systemd d'Exim réduit l'impact de toute future vulnérabilité de corruption mémoire :
# /etc/systemd/system/exim4.service.d/hardening.conf
[Service]
NoNewPrivileges=yes
MemoryDenyWriteExecute=yes
ProtectSystem=strict
PrivateTmp=yes
RestrictAddressFamilies=AF_INET AF_INET6
SystemCallFilter=@system-service
systemctl daemon-reload && systemctl restart exim4
ldd et strings, ce qui peut être moins fiable.