Backdoor in xz-utils liblzma
A multi-year social engineering campaign planted a backdoor in the xz release tarballs, hooking sshd via liblzma.
- Severity
- 10.0critical
- Vendor
- xz-utils
- Disclosed
- 29 Mar 2024
- Affected
- xz-utils 5.6.0, xz-utils 5.6.1
CVSS breakdown
- Attack vector
- Network
- Attack complexity
- Low
- Privileges required
- None
- User interaction
- None
- Scope
- Unchanged
- Confidentiality
- High
- Integrity
- High
- Availability
- High
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Analysis
The xz backdoor is the only entry on this list that is not really a vulnerability. Nobody made a mistake. It is a deliberate, patient, extremely well-executed supply-chain attack that came within weeks of putting a remote backdoor into essentially every Linux server on the internet — and was caught by accident.
#The social engineering
The technical payload is the less important half. The interesting half is how the attacker got commit rights.
xz-utils was maintained, effectively alone, by one volunteer. In 2021 an account under the name Jia Tan began contributing. The contributions were real and useful. Over roughly two years the account built a track record of legitimate work.
In parallel, a set of accounts appeared in the project's mailing lists complaining about slow releases and pressing the maintainer to add a co-maintainer. The maintainer, who had been open about being under strain, eventually handed over release authority.
By 2023 Jia Tan was signing releases. The backdoor shipped in 5.6.0 (February 2024) and 5.6.1.
Read that timeline again: roughly three years of genuine, useful open-source contribution as the setup cost. This was not opportunistic. It is the profile of an actor with institutional patience — which is most of why the consensus reading is a state programme.
#The technical payload
Equally disciplined:
- The backdoor was not in the git repository. The malicious build steps existed only in the released tarballs — the artefacts people actually download and distributions actually build from. Anyone auditing the GitHub source would find nothing.
- The payload was hidden in binary test fixtures — files that are supposed to be corrupt-looking compressed data, in a compression library, where nobody would blink at high-entropy blobs.
- A modified
build-to-host.m4in the autotools machinery extracted and assembled the payload during./configure, but only under specific conditions: building an x86-64 Linux RPM or DEB package, with gcc and the GNU linker. Building from git, on the wrong architecture, or outside the packaging path produced a clean binary.
The target was sshd. OpenSSH does not link liblzma — but several distributions patch sshd to support systemd notification, and libsystemd pulls in liblzma. So on Debian and Fedora derivatives specifically, liblzma ends up in the sshd address space.
From there the payload used an IFUNC resolver to hook symbol resolution and replace RSA_public_decrypt in the crypto path. The hook checked certificate data presented during authentication for a payload signed with the attacker's ED448 key. Correct key → the supplied command executes as root, before authentication. Wrong key → normal behaviour.
That last property is what makes this so much worse than an ordinary backdoor: it is not a static credential anyone could find and use. It is an authenticated backdoor usable only by the holder of the private key. Scanning the internet for it would reveal nothing.
#How it was caught
Andres Freund, a PostgreSQL developer, noticed that sshd was using about half a second more CPU than expected during failed logins, and that Valgrind was producing odd errors. He followed the anomaly, on his own time, out of irritation at a performance regression.
The backdoor was in Debian testing, Fedora Rawhide and openSUSE Tumbleweed. It had not yet reached Debian stable, RHEL or Ubuntu LTS. Weeks of margin.
It is not comfortable that the detection story is "one person found 500ms suspicious." No scanner, no SCA tool, no reproducible-build check and no distribution review caught it. Every automated control in the modern supply-chain security stack looked straight at this and saw nothing.
#Detection
- Version: xz/liblzma 5.6.0 and 5.6.1. Downgrade to 5.4.x.
xz --version, and check the actual library, not just the CLI package. - Distribution advisories are authoritative here — most shipped a downgrade rather than a patch.
- Practically: if you run Debian stable, RHEL or Ubuntu LTS, you were almost certainly never exposed. Rolling and testing branches in Feb–Mar 2024 are the population at risk.
- Detection scripts published at the time checked for the IFUNC hook's signature in the loaded library.
#What generalises
This one resists a tidy control.
Release artefacts are not the source. The single most transferable lesson: the tarball differed from the repository, and everyone's review looked at the repository. Reproducible builds — verifying that the published artefact is byte-for-byte what the public source produces — would have caught this immediately. This remains the strongest available answer and is still not widely adopted.
Dependency graphs are trust graphs. sshd was compromised through systemd through liblzma. Nobody chose to trust a compression library with their authentication path; the linker decided. Your real trust boundary is the transitive closure of everything linked into a privileged process.
Maintainer burnout is an attack surface. The pressure campaign on an unpaid, overextended maintainer was a deliberate part of the operation. A critical library with one exhausted volunteer is a supply-chain risk in exactly the way an unpatched CVE is, and it does not appear on any dashboard.
And the uncomfortable one: this was caught by luck. The rational assumption is that better-executed versions of this attack exist and have not been found.