31 Mar 2024, 20:32

The XZ Backdoor

Over the Easter weekend 2024, there was a big kerfuffle around a compression tool named xz. Honestly, the story is so amazing that it could be a gripping novel. In fact, what happened is not dissimilar to the book $ git commit murder My Michael Warren Lucas.

A PostgreSQL developer, Andres Freund, was running some benchmarks and trying to reduce the noise from other programs on the system. While doing so, he noticed that sshd would take more CPU than expected during logins, for about 0.5 seconds at a time.

Side note: The reason that this came up at all is that any system exposed to the internet gets regular failed login attempts via ssh, from potential attackers and security scanners of some sort.

So Andres starts looking into where the CPU time is spent and discovers that most of it is in a part of liblzma (the compression format library) and not covered by a symbol – i.e. without an indication in which function it is. This is very suspect. Digging further, it turns out that sshd is backdoored through the installation of xz version 5.6.0 or 5.6.1!

At this point, I highly recommend heading over to https://www.openwall.com/lists/oss-security/2024/03/29/4 and reading Andres’ original investigation posting. Below, I want to resume some more salient points around this story.

Why does OpenSSH even depend on xz?

Normally, it doesn’t, however several Linux distributions patch sshd to integrate systemd notifications. The systemd library to do that also happens to link against liblzma from the xz project. So perhaps the folks complaining about how systemd is so pervasive in modern Linux systems do have a point.

Who wrote the backdoor?

The malicious code has not been written by the original author and maintainer of xz, Lasse Collin. In fact, he appears to be the victim here.

The backdoor was inserted by a second xz maintainer named Jia Tan, who joined the project several years ago. The circumstances of him joining are a story that happens all over open source projects:

At some point, the main development of xz was more or less done. As lcamtuf argued, ongoing maintenance of a stable project “is as interesting as watching paint dry”. So I imagine Lasse struggling with motivation, then someone coming along and offering to become the co-maintainer. They show up with some patches ready to merge. At the same time, several people put pressure on Lasse, saying that “patches sit forever in the queue”, that they are doing a bad job and that this person should just be admitted.

Note that this was years before this backdoor.

They then do the following:

  • Jia Tan creates https://github.com/tukaani-project containing Lasse and themselves. The original xz code was hosted off GitHub on git.tukaani.org.
  • The homepage moves from Lasse’s server to a subdomain hosted on GitHub Pages, so that Jia Tan has full control over what’s on the page.
  • A workaround for a Valgrind failure is added to various distributions. Apparently, the Valgrind failure is caused by code added to later support the backdoor.
  • Jia Tan adds plenty of test files (binary archives) with innocent-sounding names to the repo. Curiously, some of them are not actually used in tests.
  • Jia Tan creates the official release tarballs on their machine.

The last two points are important for how the backdoor is hidden.

xz versions 5.6.0 and 5.6.1, both containing the backdoor, are released in late March 2024, apparently while Lasse Collin is on vacation.

How is the backdoor hidden?

The payload is effectively contained in some of the binary test archives added to the repository before. But the way they are enabled is amazingly subtle.

In open source projects using Autotools, it is common to not check in generated files (like the configure script) to the repository. After all, they can be generated at any time, right? So what happens is that the maintainer of the code (the perpetrator in this case) checks out the source at a certain tag, runs autoreconf and creates the release archive from the result (e.g. using make dist, which is part of automake). So whatever changes they do to their local copies of autoconf and/or its macros is not checked in to source control! If you look into the git repo, the code enabling the backdoor is not there at all!

What does the backdoor do?

On a Linux x86 system (and only on Linux x86), it hooks up into the signature verification routines used when checking the credentials of someone trying to log in via ssh. The exact way of working is still not fully understood as of the time of this article. According to preliminary analysis by Filippo Valsorda, the backdoor becomes active when the login attempt contains a certain client key (I was not even aware that a client key is sent in ssh logins) and runs some code by calling system. So it appears to be Remote Code Execution, a Pre-Auth Bypass, or both.

In this context, it is probably not a coincidence that some folks saw a much larger number of failed ssh login attempts over the internet:

xz 5.6.0 was released 2024-02-24, around one month ago, and it contained a backdoor.

[…]

There has been an incredible amount of SSH attacks on my server since early 2024. To give you an idea:

root@udon:~# grep -ic 2024 /etc/hosts.deny
5406

root@udon:~# grep -ic 2023 /etc/hosts.deny
763

Who is Jia Tan?

In short, we don’t know. It is probably a fake identity, just like the sock puppet accounts that were used to pressure Lasse to admit Jia into the project.

The back story is that they are Chinese and living in California. There is some speculation that they were legitimate and a second person took over their identity. But this is not confirmed, and I think it is unlikely.

Jia Tan’s GitHub account is still active, though the xz-related repos have been blocked. This does not make it easier to follow along the technical write-ups, or to check out the source for ourselves.

Jia also made 9 commits into private repositories in the last month. I wonder what those are?

In the meantime, Lasse found at least one other malicious commit in the xz source, disabling the use of Landlock sandboxing on Linux. Look at that diff and think about whether you would have spotted this in code review!

Jia also made suspicious commits to other projects, such as libarchive. Again, some of this suspicion may be overblown, but we don’t know.

Would SBOM have prevented this?

Haha lol no.

These were normal-looking releases, uploaded and signed by the regular release manager. If anything, it is helpful to be aware that a larger product contains a version of xz with the backdoor.

What are the consequences?

This could be a watershed moment for open source development. Open source development is currently a high-trust environment, and I fear that suspicion about this case is going to color all sorts of future interactions.

The thing is, all the interactions that Jia Tan had look absolutely legit and standard for open source. It is completely normal that someone who you never met shows up and offers some help and patches. Maybe you meet them years later at FOSDEM, or something. Maybe you never do.

For instance, in NetBSD, there are dozens of people who contribute under pseudonyms at this very moment. To become a developer, we require that another developer meet you in person and sign your PGP key. Maybe that’s a good idea after all.

But for instance, multiple times, I have shown up in some other open source project with a fully formed patch, saying “Here is some code to support my OS or my architecture. You probably cannot verify it as you don’t have this machine. Please apply it, I promise it’s fine.” Until now, I assumed that they would do just that, and was annoyed when they didn’t. But now? They don’t know if I am trying to insert a backdoor.

In the end, this is probably going to introduce more friction and more suspicion of contributors’ motivations into the distributed, open development process. This is bad news for all users of Free software. I would hate it if this destroys the trust-first (you might say naive) culture in open source development.

But let me also offer two more hopeful takes.

  • Diversity works. The backdoor targets the largest majority platform for servers: Linux, with systemd, on x86. Running NetBSD or FreeBSD, or perhaps another architecture such as ARM, prevents the attack from working. So by virtue of being on a less common platform, you can lower your risk. This is a basic economic argument: just like other closed source vendors (hah!), exploit writers primarily target the majority.
  • Finally, the open source community did not actually do too bad in this! Sure, it was found by a stroke of pure luck. But the malicious code had been in the wild for only about a month. And it had not made it into long-term support releases of major distributions, where it would have made it into a ton of server systems. Compared to the lead time for this attach of 3-4 years, this ended up not being a very successful operation by whichever organization is behind this. So in sum, we got away okay this time.