Share
## https://sploitus.com/exploit?id=E06430E8-210A-510A-A01B-011688E27E2F
# CVE-2026-45185 โ€” "Dead.Letter" Exim Vulnerability Scanner

A shell script for detecting whether a Linux system is vulnerable to
CVE-2026-45185, a use-after-free in the Exim mail transfer agent that can
lead to remote code execution.

Designed for use in CI/CD pipelines, configuration management tooling, and
ad-hoc system audits. Produces both human-readable and machine-readable
(JSON) output.

---

## The Vulnerability

**CVE-2026-45185** (alias: *Dead.Letter*) is a use-after-free bug in Exim's
BDAT (binary data) message body parsing, triggered when TLS is handled by
GnuTLS.

During TLS shutdown, Exim frees its TLS transfer buffer โ€” but a nested BDAT
receive wrapper can still process incoming bytes and call `ungetc()`, writing
a single `\n` byte into the freed region. That one-byte write corrupts heap
allocator metadata, from which an attacker can gain further memory primitives
and achieve remote code execution.

| Property | Detail |
|---|---|
| **CVE** | CVE-2026-45185 |
| **Alias** | Dead.Letter |
| **Type** | Use-After-Free (CWE-416) |
| **Component** | Exim BDAT/CHUNKING handler (GnuTLS builds only) |
| **Attack vector** | Network โ€” unauthenticated, requires only a TLS connection and CHUNKING extension |
| **Affected versions** | Exim 4.97 โ€“ 4.99.2, GnuTLS builds only |
| **Fixed in** | Exim 4.99.3 |
| **Discovered by** | Federico Kirschbaum, XBOW Security Lab (reported 1 May 2026) |

> **OpenSSL builds are not affected.** The vulnerability is specific to Exim
> compiled with `USE_GNUTLS=yes`. If your Exim links against OpenSSL, you are
> not vulnerable regardless of version.

---

## What the Script Checks

The script works through a decision tree, stopping and marking the system
**not vulnerable** as soon as a definitive safe condition is confirmed:

**Check 1 โ€” Exim presence**
Searches `$PATH` and common install locations (`/usr/sbin/exim`,
`/usr/sbin/exim4`, `/usr/local/sbin/exim`). If Exim is not found, the system
is not vulnerable and the script exits immediately.

**Check 2 โ€” Exim version**
Parses `exim -bV` output and compares against the affected range
(4.97 โ€“ 4.99.2). Versions โ‰ฅ 4.99.3 are treated as patched. Versions outside
the known range are marked not vulnerable (with a note if they are
unrecognised).

**Check 3 โ€” TLS library (the critical gate)**
Uses three detection methods in sequence:

1. `exim -bV` build information (most reliable โ€” Exim reports its own compile-time features, e.g. `Support for: GnuTLS`)
2. `ldd` shared library linkage
3. `strings` binary scan (fallback)

If OpenSSL is detected โ†’ verdict flips to **not vulnerable** regardless of
version. If GnuTLS is detected โ†’ the attack surface is confirmed present. If
neither can be determined โ†’ result is **inconclusive**.

**Check 4 โ€” CHUNKING/BDAT config (workaround check)**
Only runs if the system is still marked vulnerable at this point. Checks
whether `chunking_advertise_hosts` has been explicitly set to an empty value
in the Exim config, which disables BDAT advertisement and blocks the attack
vector. Handles both single-file configs and Debian's split-config layout
(`/etc/exim4/conf.d/` fragments).

> Note: if `chunking_advertise_hosts` is *absent* from the config (the
> default), Exim advertises CHUNKING to all hosts (`*`). The option must be
> explicitly set to an empty value to disable it.

**Check 5 โ€” Informational system mitigations**
Does not change the verdict, but reports on factors that affect
exploitability:

- ASLR level (`/proc/sys/kernel/randomize_va_space`) โ€” should be `2`
- glibc version โ€” 2.32+ has stronger heap metadata integrity checks
- `checksec` output for the Exim binary (PIE, RELRO, stack canaries) if `checksec` is installed
- systemd unit sandboxing: `MemoryDenyWriteExecute`, `NoNewPrivileges`, `SystemCallFilter`

---

## Requirements

- **Bash** 4.0 or later
- **Linux** with `/proc` filesystem (for ASLR check)
- Standard coreutils: `grep`, `awk`, `ldd`, `head`
- `checksec` (optional โ€” for binary hardening analysis)
- `systemctl` (optional โ€” for systemd unit inspection)
- Must be run with sufficient privilege to read the Exim config file (typically root, or a user in the `Debian-exim` group on Debian/Ubuntu)

No external dependencies are required for the core vulnerability checks.

---

## Usage

```bash
chmod +x check_cve_2026_45185.sh
./check_cve_2026_45185.sh
```

### Options

| Flag | Description |
|---|---|
| `--json` | Output results as a JSON object (see below) |
| `--quiet` | Suppress all output; only the exit code is set |
| `--no-color` | Disable ANSI colour codes (useful for log files) |
| `--help` / `-h` | Print usage information |

### Exit Codes

| Code | Meaning |
|---|---|
| `0` | Not vulnerable (or a definitive safe condition was found) |
| `1` | Vulnerable |
| `2` | Inconclusive โ€” could not determine one or more required facts; treat as potentially vulnerable |
| `3` | Script error or unsupported environment |

---

## Example Output

### Human-readable (default)

```
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 output (`--json`)

```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"
  ]
}
```

---

## CI/CD Integration

### GitHub Actions

```yaml
- 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
```

### GitLab CI

```yaml
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
```

### Ansible

```yaml
- 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 }}"
```

### Parsing JSON output with jq

```bash
# 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' /dev/null \
  | grep -i chunking
# No output = CHUNKING is disabled
```

> **This is a workaround, not a fix.** Some sending mail servers use BDAT for
> large message delivery. Disabling it may cause compatibility issues with
> those senders. Upgrade to 4.99.3 as soon as possible.

### Hardening the systemd unit (defence in depth)

Even on a patched system, adding these directives to the Exim systemd unit
reduces the impact of any future memory corruption vulnerability:

```ini
# /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
```

```bash
systemctl daemon-reload && systemctl restart exim4
```

---

## Limitations

- The script performs **static detection** only. It does not attempt to
  exploit the vulnerability or confirm exploitability under the specific
  runtime conditions of the target system.
- On systems where the Exim binary cannot be executed (e.g. permission
  constraints in a container), TLS library detection falls back to `ldd` and
  `strings`, which may be less reliable.
- Exim versions **below 4.97** are outside the known affected range for this
  specific CVE, but are unmaintained and likely vulnerable to other
  unpatched issues. Upgrading is recommended regardless.
- The script requires read access to the Exim configuration file to check
  the CHUNKING workaround. If run without sufficient privilege, the config
  check step will report inconclusive rather than failing.

---

## References

- [The Hacker News โ€” New Exim BDAT Vulnerability Exposes GnuTLS Builds to Potential Code Execution](https://thehackernews.com/2026/05/new-exim-bdat-vulnerability-exposes.html)
- [Exim project โ€” Security documentation](https://www.exim.org/static/doc/security/)
- [Exim specification โ€” CHUNKING (`chunking_advertise_hosts`)](https://www.exim.org/exim-html-current/doc/html/spec_html/ch-main_configuration.html)
- [Exim specification โ€” TLS configuration](https://www.exim.org/exim-html-current/doc/html/spec_html/ch-encrypted_smtp_connections_using_tlsssl.html)
- [XBOW Security Lab](https://xbow.com)