Free software's not-so-eXZellent adventure
[LWN subscriber-only content]
Welcome to LWN.netThe following subscription-only content has been made available to you by an LWN subscriber. Thousands of subscribers depend on LWN for the best news from the Linux and free software communities. If you enjoy this article, please consider accepting the trial offer on the right. Thank you for visiting LWN.net! |
|
A common theme in early-days anti-Linux FUD was that, since anybody can contribute to the code, it cannot be trusted. Over two decades later, one rarely hears that line anymore; experience has shown that free-software communities are not prone to shipping overtly hostile code. But, as the backdooring of XZ has reminded us, the embedding of malicious code is, unfortunately, not limited to the proprietary realm. Our community will be busy analyzing this incident for some time to come, but clear conclusions may be hard to come by.
The technical details of the attack are fascinating in many ways. See the companion article for more about that aspect of things.
For those needing a short overview: the XZ package performs data compression; it is widely distributed and used in many different places. Somebody known as "Jia Tan" managed to obtain maintainer-level access to this project and used that access to insert a cleverly concealed backdoor that, when the XZ library was loaded into an OpenSSH server process, would provide an attacker with the ability to run arbitrary code on the affected system. This code had found its way into some testing distributions and the openSUSE Tumbleweed rolling distribution before being discovered by Andres Freund. (See this page for a detailed timeline.)
The hostile code was quickly removed and, while it is too soon to be sure, it appears that it was caught before it could be exploited. Had that discovery not happened, the malicious code could have found its way onto vast numbers of systems. The consequences of a success at that level are hard to imagine and hard to overstate.
Social engineering
Like so many important projects, XZ was for years the responsibility of a single maintainer (Lasse Collin) who was keeping the code going on his own time. That led to a slow development pace at times, and patches sent by others often languished. That is, unfortunately, not an unusual situation in our community.
In May 2022, Collin was subjected to extensive criticism in this email thread (and others) for failing to respond quickly enough to patches. That, too, again unfortunately, is not uncommon in our community. Looking back now, though, the conversation takes on an even more sinister light; the accounts used to bully the maintainer are widely thought to have been sock puppets, created for this purpose and abandoned thereafter. In retrospect, the clear intent was to pressure Collin into accepting another maintainer into the project.
During this conversation, Collin mentioned (more than once) that he had been receiving off-list help from Tan, and that Tan might be given a bigger role in the future. That, of course, did happen, with devastating effects. Tan obtained the ability to push code into the repository, and subsequently abused that power to add the backdoor over an extended period of time. As well as adding the backdoor, Tan modified the posted security policy in an attempt to contain the disclosure of any vulnerabilities found in the code, changed the build system to silently disable the Landlock security module, redirected reports from the OSS-Fuzz effort, and more.
Once the malicious code became part of an XZ release, Tan took the campaign to distributors in an attempt to get them to ship the compromised versions as quickly as possible. There was also a series of patches submitted to the kernel that named Tan as a maintainer of the in-kernel XZ code. The patches otherwise look innocuous on their face, but do seem intended to encourage users to update to a malicious version of XZ more quickly. These patches made it as far as linux-next, but never landed in the mainline.
Much has been made of the fact that, by having an overworked and uncompensated maintainer, XZ was especially vulnerable to this type of attack. That may be true, and support for maintainers is a huge problem in general, but it is not the whole story here. Even paid and unstressed maintainers are happy to welcome help from outsiders. The ability to take contributions from — and give responsibility to — people we have never met from a distant part of the world is one of the strengths of our development model, after all. An attacker who is willing to play a long game has a good chance of reaching a position of trust in many important projects.
This whole episode is likely to make it harder for maintainers to trust helpful outsiders, even those they have worked with for years. To an extent, that may be necessary, but it is also counterproductive (we want our maintainers to get more help) and sad. Our community is built on trust, and that trust has proved to be warranted almost all of the time. If we cannot trust our collaborators, we will be less productive and have less fun.
Closing the door
As might be expected, the Internet is full of ideas of how this attack could have been prevented or detected. Some are more helpful than others.
There have been numerous comments about excess complexity in our systems. They have a point, but few people add complexity for no reason all; features go into software because somebody needs them. This is also true of patches applied by distributors, which were a part of the complex web this attack was built on. Distributors, as a general rule, would rather carry fewer patches than more, and don't patch the software they ship without a reason. So, while both complexity and downstream patching should be examined and avoided when possible, they are a part of our world that is not going away.
In the end, the specific software components that were targeted in this attack are only so relevant. Had that vector not been available, the attacker would have chosen another. The simple truth is that there are many vectors to choose from.
There is certainly no lack of technical and process questions that should be asked with regard to this attack. What are the dependencies pulled in by critical software, do they make sense, and can they be reduced? Why do projects ship tarballs with contents that are not found in their source repository, and why do distributors build from those tarballs? How can we better incorporate the ongoing reproducible-builds work to catch subtle changes? Should testing infrastructure be somehow separated from code that is built for deployment? What are the best practices around the management of binary objects belonging to a project? Why are we still using ancient build systems that almost nobody understands? How can we get better review of the sorts of code that makes eyes glaze over? What is the proper embargo policy for a problem like this one?
These are all useful questions that need to be discussed in depth; hopefully, some useful conclusions will come from them. But it is important to not get hung up on the details of this specific attack; the next one is likely to look different. And that next attack may well already be underway.
On the unhelpful side, the suggestion from the OpenSSF that part of the problem was the lack of an "OpenSSF Best Practices badge" is unlikely to do much to prevent the next attack. (Note that the organization seems to have figured that out; see the Wayback Machine for the original version of the post). The action by GitHub to block access to the XZ repository — after the horse had long since left the barn, moved to a new state, and raised a family — served only to inhibit the analysis of the problem while protecting nobody.
The source
This attack was carried out in a careful and patient fashion over the course of at least two years; it is not a case of a script kiddie getting lucky. Somebody — or a group of somebodies — took the time to identify a way to compromise a large number of systems, develop a complex and stealthy exploit, and carry out an extensive social-engineering campaign to get that exploit into the XZ repository and, from there, into shipping distributions. All of this was done while making a minimum of mistakes until near the end.
It seems clear that considerable resources were dedicated to this effort. Speculating on where those resources came from is exactly that — speculation. But to speculate that this may have been a state-supported effort does not seem to be going out too far on any sort of limb. There are, undoubtedly, many agencies that would have liked to obtain this kind of access to Linux systems. We may never know whether one of them was behind this attempt.
Another thing to keep in mind is that an attack of this sophistication is unlikely to limit itself to a single compromise vector in a single package. The chances are high that other tentacles, using different identities and different approaches, exist. So, while looking at what could have been done to detect and prevent this attack at an earlier stage is a valuable exercise, it also risks distracting us from the next attack (or existing, ongoing attacks) that do not follow the same playbook.
Over the years, there have not been many attempts to insert a backdoor of this nature — at least, that we have detected — into core free-software projects. One possible explanation for that is that our software has been sufficiently porous that a suitably skilled attacker could always find an existing vulnerability to take advantage of without risking the sort of exposure that is now happening around the XZ attack. An intriguing (and possibly entirely wishful) thought is that the long and ongoing efforts to harden our systems, move to better languages, and generally handle security issues in a better way has made that avenue harder, at least some of the time, pushing some attackers into risky, multi-year backdoor attempts.
Finally
In the numerous discussions sparked by this attack, one can readily find two seemingly opposing points of view:
- The XZ episode shows the strength of the free-software community. Through our diligence and testing, we detected a sophisticated attack (probably) before it was able to achieve its objectives, analyzed it, and disabled it. (Example).
- The world was saved from a massive security disaster only by dint of incredible luck. That such an attack could get so far is a demonstration of the weakness of our community; given our longstanding sustainability problems, an attack like this was inevitable at some point. (Example).
In the end, both of those points of view can be valid at the same time. Yes, there was a massive bit of luck involved in the detection of this attack, and yes, the support for maintainers (and many other contributors) is not what it needs to be. But, to paraphrase Louis Pasteur, chance favors the prepared development community. We have skilled and curious developers who will look into anomalous behavior, and we have a software environment that facilitates that sort of investigation. We never have to accept that a given software system just behaves strangely; we have, instead, gone to great lengths to ensure that it is possible to dig in and figure out why that behavior is happening — and to fix it. That is, indeed, a major strength; that, along with luck and heroic work, is what saved us.
We must hope that we can improve our game enough that our strengths will
save us the next time as well. There is a good chance that our community,
made up of people who just want to get something done and most of whom are
not security experts, has just been attacked by a powerful adversary with
extensive capabilities and resources. We are not equipped for that kind of
fight. But, then, neither is the proprietary world. Our community has
muddled through a lot of challenges to get this far; we may yet muddle
through this one as well.
Did you like this article? Please accept our trial subscription offer to be able to see more content like it and to participate in the discussion.
(Log in to post comments)
Free software's not-so-eXZellent adventure
Posted Apr 2, 2024 17:18 UTC (Tue) by jd (subscriber, #26381) [Link]
The fact that open source has had its share of disastrous vulnerabilities and hostile maintainers (the case of the missing python module...) shows many eyes isn't enough, even when there actually are many eyes.
I don't know what the answer is, but I do know that any solutions will depend on trust somewhere. Even in business. If we can't fix trust, the problem won't get fixed.
Free software's not-so-eXZellent adventure
Posted Apr 2, 2024 17:41 UTC (Tue) by myUser (subscriber, #58242) [Link]
Free software's not-so-eXZellent adventure
Posted Apr 2, 2024 17:45 UTC (Tue) by Wol (subscriber, #4433) [Link]
"With sufficient eyes, all problems are shallow" is, I believe, the correct quote (near enough).
It only takes one pair of eyes to spot the problem, and then the many eyes will turn and yes, the problem is shallow. As was amply demonstrated both here, and on many other occasions.
It's widely said about security that the bad guys only have to strike lucky once, while the good guys have to strike lucky all the time. This proves the same holds true in reverse - the good guys only have to strike lucky once, while the bad guys have to strike lucky every time.
Cheers,
Wol
Free software's not-so-eXZellent adventure
Posted Apr 3, 2024 6:08 UTC (Wed) by AdamW (subscriber, #48457) [Link]
Intelligence agencies have recognized, for a long time, that they will *always* be subject to infiltration attempts. They also realize that it is almost impossible to catch all of these. This means that, in order for an intelligence agency to ever get any work done, it has to recognize that at *some* point, it will probably trust someone who should not be trusted. It's not an ideal situation, but it may not be a completely fixable one. Similarly, in F/OSS, it may not be possible to entirely "fix trust".
It might be intriguing to look at some of the coping mechanisms from that world and see if they can be translated to F/OSS...
Free software's not-so-eXZellent adventure
Posted Apr 3, 2024 10:38 UTC (Wed) by smurf (subscriber, #17840) [Link]
Certainly they can. One such mitigation is "layers". Ideally, a compromised agent can only betray their direct contacts, not the contacts' contacts in turn.
The OS equivalent is compartmentalization. The build system cannot write to the source (this is mostly true). The test system cannot write to the build (… should not … this is one of the loopholes the XZ exploit used). The packager can only package; right now it can also add arbitrary shell scripts that get executed when the package is installed, but at least some script adhoc-ery can be fixed declaratively. systemd's tempfiles language supports a large subset of operations that these scripts are commonly used for: see "man 5 tmpfiles.d" for details.
> "fix trust"
Conversely, the source should be used for the build. *Only* the *signed* source (as in, "git tag -s"). Not some assumed-to-be-the-source tarball somebody cooked up in their backyard (another loophole which the XZ exploit used) and/or which is accompanied by security theater, in the form of an unsigned SHA* checksum alongside the tarball, on the same web server …
Debian's Ian Jackson has been working on converting its 30-year-old build architecture to something modern and reasonably sane; see https://peertube.debian.social/w/pav68XBWdurWzfTYvDgWRM
I can only assume that both Debian and other distributions will now accelerate their efforts to do this.
Yes, this seems like a game of whack-a-mole, but every mole whacked is one that won't re-surface.
Free software's not-so-eXZellent adventure
Posted Apr 3, 2024 16:40 UTC (Wed) by draco (subscriber, #1792) [Link]
Of course, both should be disallowed
Free software's not-so-eXZellent adventure
Posted Apr 3, 2024 12:08 UTC (Wed) by pizza (subscriber, #46) [Link]
Those "coping mechanisms" invariably involve a considerable amount of intentional inefficiency (eg "ridiculous levels of compartmentalization" and "process"), along with a commensurate budget and manpower to implement and sustain all of that.
Free software's not-so-eXZellent adventure
Posted Apr 2, 2024 17:32 UTC (Tue) by cen (subscriber, #170575) [Link]
The most likely scenario I see is that xz will gradually be dropped as dependency and replaced with alternatives.
Free software's not-so-eXZellent adventure
Posted Apr 2, 2024 17:48 UTC (Tue) by Wol (subscriber, #4433) [Link]
But if it triggers a serious effort to rid distros of the worst scoring projects, it could quite possibly achieve wonders pretty quickly.
In two ways. Firstly, if there are several packages occupying the same niche, resources would tend to concentrate on just one. And secondly, it'll push packages to get a maintainer - even if it does just become a job for someone at RH, or Canonical, or SUSE, or LF ...
Cheers,
Wol
Free software's not-so-eXZellent adventure
Posted Apr 2, 2024 21:47 UTC (Tue) by magfr (subscriber, #16052) [Link]
Free software's not-so-eXZellent adventure
Posted Apr 3, 2024 6:47 UTC (Wed) by LtWorf (subscriber, #124958) [Link]
This would leave out stuff like: the kernel, gcc, KDE, libreoffice, all of distribution tools like dpkg and apt…
Free software's not-so-eXZellent adventure
Posted Apr 2, 2024 20:50 UTC (Tue) by pebolle (subscriber, #35204) [Link]
Perhaps that will happen.
The scenario that I'd prefer is for the XZ software to be dropped everywhere. It's cost/benefit ratio is by now dismal. And also for its original maintainer to be told to switch to activities not involving software. Because his name will be tainted in that field forever.
Switching fields
Posted Apr 2, 2024 21:04 UTC (Tue) by corbet (editor, #1) [Link]
I think that is somewhat harsh with regard to Lasse Collin. Perhaps you are sharp enough that you would never fall prey to a focused social-engineering campaign like that; I'm not at all sure that I am.OTOH I would surely understand if he concluded that he wanted to switch to goat farming or something equally far removed after having had this experience.
Switching fields
Posted Apr 2, 2024 21:22 UTC (Tue) by pebolle (subscriber, #35204) [Link]
Being not particularly sharp I could certainly fall prey to such a campaign.
The point is that Lasse Collin was a maintainer of a project that was subjected to an exceptionally serious exploit. Isn't that enough to tell him to shift his spare time activities?
Switching fields
Posted Apr 2, 2024 21:33 UTC (Tue) by Wol (subscriber, #4433) [Link]
In that case, shouldn't we ALL drop working on Linux and move to other activities - ESPECIALLY YOU, seeing as you admit you would easily fall prey to a similar attack?
Have you heard the saying "once bitten, twice shy"? I'd actually think Lasse SHOULD work on more similar projects, if he wants too - he's unlikely to get caught the same way twice. Although if he did want to give up, I wouldn't be surprised.
At the end of the day, punishing people for making mistakes is extremely counter-productive. Let's not go there ...
Cheers,
Wol
Switching fields
Posted Apr 2, 2024 21:33 UTC (Tue) by Sesse (subscriber, #53779) [Link]
Why? “I don't want unlucky maintainers”? Or would you tell basically everyone in the FOSS world who would plausibly have fallen for the same ruse to do the same? (There wouldn't be a lot of maintainers around then.)
Switching fields
Posted Apr 2, 2024 21:53 UTC (Tue) by pebolle (subscriber, #35204) [Link]
I don't want maintainers publicly declaring their incapability to maintain their project (because of "mental health issues") .
> Or would you tell basically everyone in the FOSS world who would plausibly have fallen for the same ruse to do the same? (There wouldn't be a lot of maintainers around then.)
If they had fallen for the same ruse the honourable thing would be to say: "I messed up big time. I'm sorry. I won't be doing FOSS any more."
Switching fields
Posted Apr 2, 2024 21:57 UTC (Tue) by mb (subscriber, #50428) [Link]
This is really uncalled for.
The xz maintainer does not deserve this.
Switching fields
Posted Apr 2, 2024 22:00 UTC (Tue) by Sesse (subscriber, #53779) [Link]
Why?
> If they had fallen for the same ruse the honourable thing would be to say: "I messed up big time. I'm sorry. I won't be doing FOSS any more."
So will the world be better off for that? Do you think the average security of FOSS packages will increase if the xz maintainer goes away? Who should maintain the package in their stead? And how do these standards differ from e.g. zlib's situation? (zlib was recently de facto supplanted by zlib-ng, led by a virtually unknown maintainer. I happen to know them and know that they are trustworthy, but how would you distinguish them from Jia Tan without that knowledge?)
Switching fields
Posted Apr 2, 2024 22:04 UTC (Tue) by corbet (editor, #1) [Link]
I have a sense that this subthread could go bad quickly.How about we stop here; you've said your piece, and it is quite clear that others disagree with you. I suspect that discussing this idea further will not bring much joy to anybody.
Switching fields
Posted Apr 2, 2024 23:22 UTC (Tue) by viro (subscriber, #7872) [Link]
Note: I've no idea what condition Lasse had, but your claim is generic enough to have the above fit it. And when read that way, you do come across as a really vile piece of work. Self-righteous references to honourable behaviour and lovely uses of passive voice ("be told ...") only strengthen that impression.
Switching fields
Posted Apr 3, 2024 10:40 UTC (Wed) by farnz (subscriber, #17727) [Link]
Would you prefer that the maintainer hid their issues, and was blackmailed by a malicious entity into putting their code in place for them, hiding the very existence of Jia Tan?
That's the alternative direction that you're opening up if maintainers can't talk about their problems without being forced to stand down - and I contend that it's worse to have a maintainer open to blackmail (so we cannot, after the fact, determine how far back we need to go in the commit history to predate the malicious comaintainer) than to have a malicious actor obtain comaintainership under their own identity (where we can at least assume that while Jia Tan's changes must be treated as probably malicious, the previous maintainer's commits can be treated as well-intended).
Switching fields
Posted Apr 2, 2024 21:39 UTC (Tue) by mb (subscriber, #50428) [Link]
No? What is wrong with you? Seriously?
Switching fields
Posted Apr 2, 2024 21:49 UTC (Tue) by chris_se (subscriber, #99706) [Link]
So anybody who ever trusted the wrong person should be seen as a pariah? And in your eyes that should last forever? I'm just speechless at this horrible view of the world you are espousing here.
Switching fields
Posted Apr 2, 2024 22:06 UTC (Tue) by pebolle (subscriber, #35204) [Link]
My horrible view of the world is that if you screw up big time, and yes, this is screwing up big time, you take responsibility. In this case by retracting from this field.
Switching fields
Posted Apr 3, 2024 0:10 UTC (Wed) by JoeBuck (subscriber, #2330) [Link]
That's a foolish way to manage people. Someone who's been burned by such a sophisticated operation is more likely to be cautious in the future than some arrogant person who is convinced that he cannot be conned, and the project needs a capable, experienced maintainer.
But ideally he'd get help from someone who is paid by a company that depends on this library. Probably 20% time would suffice to take the load off, and the employer can vouch for the person.
Switching fields
Posted Apr 3, 2024 5:57 UTC (Wed) by ebee_matteo (subscriber, #165284) [Link]
Fun fact! 80% of businesses fail within 20 years.
https://clarifycapital.com/blog/what-percentage-of-busine...
If also 80% of business owner who have "screwed up" to the point of closing down then "retracted from the field", I don't think humanity would get much done.
My point goes with the old adage: errare humanum est. Learning from one mistakes is what matters.
As a FOSS contributor and maintainer with a treatable mental illness, and having known a big amount of likewise people over the years, I take deep exception with your stance.
Maybe showing empathy and understanding that it is hard for one person to contrast state-sponsored attempts spanning years (look at SolarWinds too, Cisco WebEx, Zoom...) would mean less time spent on forums, and more time doing code reviews.
The real problem is that everybody uses FOSS software even for commercial products, but very few companies invest time to contribute back, especially when it comes to security reviews.
Therefore, I would like to applaud Collin for his courage to state his condition publicly and being so transparent about it.
If you are reading this, a big hug goes out to you! You are not alone!
Free software's not-so-eXZellent adventure
Posted Apr 2, 2024 22:15 UTC (Tue) by cesarb (subscriber, #6266) [Link]
> Perhaps that will happen.
It's already happening, and it's been happening for a while, independent of the present events.
The reason is the existence of ZSTD, which at its higher settings has nearly the same compression ratio as XZ, but with much better decompression speed. Many uses of LZMA/XZ have been gradually migrating to ZSTD; newer uses will probably skip GZIP and LZMA and go straight to ZSTD.
Of course, compatibility means that a LZMA/XZ decoder will still be necessary for a long time, for things which had used a LZMA/XZ encoder in the past (and this includes systemd, for its journal format, since users might still want to read log files which were encoded using LZMA, even when newer logs are being written using ZSTD).
Free software's not-so-eXZellent adventure
Posted Apr 2, 2024 23:44 UTC (Tue) by cozzyd (subscriber, #110972) [Link]
Free software's not-so-eXZellent adventure
Posted Apr 2, 2024 17:35 UTC (Tue) by willy (subscriber, #9762) [Link]
Agreed that Free Software is in no worse a situation than Binary Software, so there's no reason to grumble about the development model. Arguably it's the responsibility of the distributions to get changes coming from upstream, but realistically there isn't the developer time to do that (can you imagine trying to verify all the changes between gcc-11 and gcc-12?)
I don't have a solution here. Just agreeing that there are a lot of attack vectors.
Free software's not-so-eXZellent adventure
Posted Apr 2, 2024 17:46 UTC (Tue) by flussence (subscriber, #85566) [Link]
The whole thing has me thinking about libav now.
Free software's not-so-eXZellent adventure
Posted Apr 2, 2024 18:04 UTC (Tue) by mbiebl (subscriber, #41876) [Link]
Free software's not-so-eXZellent adventure
Posted Apr 2, 2024 18:32 UTC (Tue) by NYKevin (subscriber, #129325) [Link]
Part of this is that maintainers need to get better at saying "no," and the other part is that users, distros, etc. all need to get better at hearing "no." Then this kind of harassment would be seen as unacceptable. In the current culture, the emails asking Collin to bring on another maintainer look benign (they're not flaming, rude, or even all that demanding). We ought to get to a point where asking a maintainer to bring on another maintainer is Just Not Done unless you're personally volunteering to be that other maintainer.
Volunteering to be the maintainer
Posted Apr 2, 2024 19:31 UTC (Tue) by corbet (editor, #1) [Link]
Of course, that's exactly what "Jia Tan" did; the only difference was using the sock puppets to play the "bad cop" part of the game.
Volunteering to be the maintainer
Posted Apr 2, 2024 20:24 UTC (Tue) by NYKevin (subscriber, #129325) [Link]
* Ideally, people complaining about a lack of activity would be disregarded as background noise, so Collin would have felt less pressure to add a maintainer.
* Ideally, not having enough maintainers would just not be seen as a big problem in the first place. You should make somebody a maintainer after they've done excellent work for long enough that your sign-off is just a rubber stamp. It should not be a game of "I need a maintainer, that person is available and willing, I'll use them." The most effective way to eliminate that temptation is to cut it off at the "I need a maintainer" step.
Volunteering to be the maintainer
Posted Apr 3, 2024 2:25 UTC (Wed) by Paf (subscriber, #91811) [Link]
Volunteering to be the maintainer
Posted Apr 3, 2024 11:51 UTC (Wed) by smurf (subscriber, #17840) [Link]
People (*especially* reasonable people) are notoriously bad at ignoring background noise, for good evolutionary reasons – which unfortunately are counter-productive in a world where social accountability doesn't apply to sock puppets.
Free software's not-so-eXZellent adventure
Posted Apr 3, 2024 9:27 UTC (Wed) by sune (subscriber, #40196) [Link]
https://github.com/microsoft/vcpkg/issues/37197 (please update xz in vcpkg to 5.6.0) ...
Free software's not-so-eXZellent adventure
Posted Apr 3, 2024 10:01 UTC (Wed) by mbiebl (subscriber, #41876) [Link]
The actions of this Neustradamus account seem very suspicious at this point and I would be very cautious.
Free software's not-so-eXZellent adventure
Posted Apr 3, 2024 11:20 UTC (Wed) by Phantom_Hoover (subscriber, #167627) [Link]
Free software's not-so-eXZellent adventure
Posted Apr 3, 2024 21:19 UTC (Wed) by flussence (subscriber, #85566) [Link]
Free software's not-so-eXZellent adventure
Posted Apr 2, 2024 18:08 UTC (Tue) by bredelings (subscriber, #53082) [Link]
Part of the problem here seemed to be that the exploit code is in some sense very distant from the exploit target. If any library that is transitively linked into an executable can override any function in the executable, then the intuition of most programmers is going to be wrong.
So, in addition to making it clear which binary blobs make it into an executable -- AFTER it is dynamically linked -- maybe we should also be concerned about what you might call "long-distance effects" that are unintuitive or hard to reason about?
Free software's not-so-eXZellent adventure
Posted Apr 2, 2024 19:05 UTC (Tue) by tux3 (subscriber, #101245) [Link]
If we spend time closing this hole, attackers will simply find another way. There's no shortage of ways for a library to cause headaches after malicious code sneaks its way in. But it's particularly bad when it gets to run before main(), in a library that would otherwise not be called at all! We SHOULD force attackers to spend time finding something different the next time around.
It has to be in a systematic way that we make these attacks more expensive.
We can't make humans infallible; we can't stop trusting contributors entirely.
I've seen a lot of critique of people trying to find technical solutions to the backdoor situation. But look how exploiting memory safety bugs has become harder and more expensive, year after year. That wasn't because humans stopped writing bugs! It was a series of technical solution over the years. None of which solved the problem completely, mind you!
But all of them helped.
Free software's not-so-eXZellent adventure
Posted Apr 2, 2024 19:26 UTC (Tue) by epa (subscriber, #39769) [Link]
Free software's not-so-eXZellent adventure
Posted Apr 2, 2024 21:07 UTC (Tue) by ms (subscriber, #41272) [Link]
In other languages, sure, you might want specialised implementations, but you do that with a function pointer, and you certainly don't get to violate lexical scope. Unless there's some really compelling use case for ifuncs to have omnipotent powers, it seems a badly conceived feature.
That said, I totally buy the argument that a well resourced team would not have been deterred by the absence of ifuncs.
Free software's not-so-eXZellent adventure
Posted Apr 2, 2024 21:38 UTC (Tue) by dezgeg (subscriber, #92243) [Link]
As far as I understood, ifuncs itself are not the method to achieve this. It's just a way to gain execution whenever a library is loaded, just like .init (which is used for things like calling global constructons). The actual method to hook RSA_public_decrypt() is via audit hook (see man rtld-audit).
Now, it's still possible that using the ifunc mechanism made things somewhat simpler for the backdoor developer (perhaps ifunc resolvers are called in an earlier stage than .init functions, or something), but fact is .init still would have been a way to get liblzma code to execute in the sshd process (and .init can't be removed without breaking metric tons of stuff).
Free software's not-so-eXZellent adventure
Posted Apr 2, 2024 22:15 UTC (Tue) by andresfreund (subscriber, #69562) [Link]
It'd have been harder / noisier, I suspect. From what I can tell .init etc do get processed after symbol resolution and thus after the GOT has been remapped read-only. Of course you could still do nasty stuff, but it'll either be harder to have sufficient information about the client (and thus whether to execute a payload), or noisier (remapping the GOT RW).
Free software's not-so-eXZellent adventure
Posted Apr 3, 2024 1:48 UTC (Wed) by dezgeg (subscriber, #92243) [Link]
Another idea that comes to mind is fopencookie() could be used to hook stdout/stderr and use that to deliver the payload (assuming sshd includes enough info there about failed connection attempts)... there's just so many different opportunities. Also detection chances could probably be reduced by simply disabling the backdoor for say, 90% of the connections (pthread_atfork() perhaps) while still remaining useful.
Free software's not-so-eXZellent adventure
Posted Apr 3, 2024 13:59 UTC (Wed) by jejb (subscriber, #6654) [Link]
Free software's not-so-eXZellent adventure
Posted Apr 3, 2024 14:35 UTC (Wed) by farnz (subscriber, #17727) [Link]
The problem with "shouldn't call the ifunc to perform the choice test until we actually need to resolve the symbol" is that an attacker can just redirect a symbol that matters to you; for example, if I supply an IFUNC for memcpy, then my IFUNC is called as soon as your program calls memcpy.
This is why I believe that there's two ELF design decisions that interact to surprise you - the other one is that the symbol import doesn't tell the linker which library it expects the symbol to come from, so any symbol can be indirected by any dependency.
Free software's not-so-eXZellent adventure
Posted Apr 3, 2024 14:51 UTC (Wed) by jejb (subscriber, #6654) [Link]
The way ifuncs currently work for dynamic libraries is that you can only do one for your own symbols, so liblzma can't use an ifunc to intercept memcpy, only glibc can do that.
So to look at this concrete example: liblzma couldn't use an ifunc to redirect RSA_public_decrypt (the object of its attack), it had to use an ifunc on one of its own functions to install an audit hook to redirect the symbol resolution for RSA_public_decrypt that allowed it to hijack the symbol in another library.
Free software's not-so-eXZellent adventure
Posted Apr 3, 2024 15:21 UTC (Wed) by ms (subscriber, #41272) [Link]
That seems a really good example: I have no doubt it would be technically possible for the dynamic linker / elf loader to allow ifuncs for symbols that are defined elsewhere - sure you might have to do it lazily because maybe that symbol hasn't been defined yet, but I'm sure it could be done. But instead, it has been _chosen_ that you can only put ifuncs it on your own functions. So it doesn't seem that much of a leap to also choose "you can only install audit hooks on your own symbols", or, more generally, "pre main, you can't do anything to symbols you've not defined yourself".
Free software's not-so-eXZellent adventure
Posted Apr 3, 2024 15:22 UTC (Wed) by farnz (subscriber, #17727) [Link]
liblzma can, however, supply a memcpy symbol, and with a bit of careful squirrelling, be set up so that its IFUNC causes it to redirect to the normal memcpy. This sort of symbol redirection game is designed into ELF (although it's not necessary for a dynamic linker to do this - Apple's Mach-O format has symbol tell you which library to import from).
So liblzma can use an IFUNC to redirect RSA_public_decrypt; it's just that in doing so, it makes RSA_public_decrypt visible in the exports list of liblzma, which would make the attack less stealthy.
Free software's not-so-eXZellent adventure
Posted Apr 3, 2024 16:15 UTC (Wed) by jejb (subscriber, #6654) [Link]
No, it can't. If you get two identical global scope non weak symbols the dynamic linker will throw a duplicate symbol error. If you try to do a local scope instead (which actually indirect dependencies get by default), it won't get resolved until used in that scope (so the resolution in sshd would always pick up the global scope symbol in glibc). You could possibly get around this using versioning, but, assuming ifunc on resolution is implemented, your ifunc wouldn't get called until something requests that specific version of memcpy ... which wouldn't happen for the binary in question.
Free software's not-so-eXZellent adventure
Posted Apr 3, 2024 16:17 UTC (Wed) by farnz (subscriber, #17727) [Link]
It can - it supplies a weak symbol, and at least in my experiments, that's enough to trigger IFUNC resolution from my attacking binary. Maybe this is a bug, but it's still a problem.
Free software's not-so-eXZellent adventure
Posted Apr 2, 2024 22:28 UTC (Tue) by fenncruz (subscriber, #81417) [Link]
Free software's not-so-eXZellent adventure
Posted Apr 3, 2024 12:03 UTC (Wed) by smurf (subscriber, #17840) [Link]
They might well be, but that's irrelevant since once you have an adversarial foothold in some library or other, running as root, you can do pretty much anything anyway, ifunc or .init or hijacked symbol.
More to the point: using an ifunc in order to choose the best implementation is fairly standard for crypto or compression code, thus doesn't jump at you when you look at the library's metadata. On the other hand, .init is used to build static objects and similar stuff which a reasonably-coded multi-thread-capable library should have no business requiring. The fact that it's easier to get gdb to trace code in .init sections than in ifuncs might be relevant too.
Free software's not-so-eXZellent adventure
Posted Apr 3, 2024 12:44 UTC (Wed) by ms (subscriber, #41272) [Link]
(ignoring the "running as root" clause)
I think this is maybe getting to the nub of it: if you link with a library, are you implicitly trusting it, to the extent that you're willing for it to write all over "your" memory, including code?
It's possible that for some of us who are used to thinking in terms of microservices, containers, etc etc, it doesn't seem hard to imagine a world where the answer is "no, I'm not trusting it that far - it can have its own memory, just like it has its own namespace, and its own scopes, but it doesn't get to interfere with mine". To me, it seems pretty crazy that all these languages typically enforce lexical scoping rules, but apparently glibc, with a combination of ifuncs and audit hooks, allows complete violation of the compartmentalisation that lexical scoping creates.
For some of us who are (I'm guessing) more experienced C/C++/kernel devs, there's both tradition, and good reason as to why believing/hoping/pretending the trust isn't absolute, is misguided.
Free software's not-so-eXZellent adventure
Posted Apr 3, 2024 15:32 UTC (Wed) by farnz (subscriber, #17727) [Link]
You don't even need to be thinking in terms of microservices etc; Apple's dynamic linker requires imported symbols to be annotated with the library that's expected to supply the symbol, and thus most of the time, when you link against a library, you're only bringing it in for its symbols. I don't know if it has an equivalent of IFUNC, nor when static constructors are run (when a library is loaded, or when you first access a symbol from the library - both would be fine within the letter of C++).
Free software's not-so-eXZellent adventure
Posted Apr 2, 2024 22:08 UTC (Tue) by khim (subscriber, #9252) [Link]
> But it's particularly bad when it gets to run before main(), in a library that would otherwise not be called at all!You only need to use global C++ constructor for that. No need to even use any non-portable tricks.
Any OS that doesn't support such capability couldn't be called C++ compliant, it's as simple as that.
> We SHOULD force attackers to spend time finding something different the next time around.By forcing everyone to switch to a language which doesn't have such capabilities, like Rust? An interesting proposal, but entirely non-practical, at least as short-term solution.
C++ is just too widely used in our world to just go and kick it out from our ecosystem.
> But all of them helped.And they added enough complexity, by now, that proper solution without all these mitigations, but with capabilties in hardware is probably more efficient already and if not it would be more efficient then pile of hacks, that we are creating, very soon.
Free software's not-so-eXZellent adventure
Posted Apr 2, 2024 22:49 UTC (Tue) by excors (subscriber, #95769) [Link]
Rust does have such capabilities:
#[used]
#[link_section = ".ctors"]
static CONSTRUCTOR: extern fn() = before_main;
extern fn before_main() { ... }
The language isn't the issue.
Free software's not-so-eXZellent adventure
Posted Apr 2, 2024 23:12 UTC (Tue) by khim (subscriber, #9252) [Link]
> Rust does have such capabilities:That's not Rust. That's platform-specific extension. Try to compile and run your code on Windows.
C++, on the other hand, have that capability as core part of it's design. One couldn't even use cin/cout without it (amount many other things) and it's regular feature used by thousands of libraries.
Free software's not-so-eXZellent adventure
Posted Apr 3, 2024 8:29 UTC (Wed) by pbonzini (subscriber, #60935) [Link]
Free software's not-so-eXZellent adventure
Posted Apr 3, 2024 9:01 UTC (Wed) by excors (subscriber, #95769) [Link]
For dynamic global `static` initialisation you need something like https://crates.io/crates/ctor , which warns "Rust's philosophy is that nothing happens before or after main and this library explicitly subverts that". That does the `#[link_section]` thing, with variants for Windows and macOS.
That crate has 48M downloads and 272 reverse dependencies, so it's not an official language feature but you probably still wouldn't want to design an OS that doesn't support equivalent execution-before-main functionality, as it would cause too many compatibility problems even in a world with no C/C++.
Free software's not-so-eXZellent adventure
Posted Apr 3, 2024 6:01 UTC (Wed) by tux3 (subscriber, #101245) [Link]
Those run after relro, so that you can't overwrite the GOT.
This backdoor makes extensive use of GOT overwrites, they like to hide what they're doing by hijacking a benign function like _cpuid, so that at first glance someone might think this is normal code.
The GOT is also a much sinpler overwrite than trying to patch .text or watch for future function pointers to appear in memory that could be overwritten. Way too easy.
>And they added enough complexity, by now, that proper solution without all these mitigations, but with capabilties in hardware is probably more efficient already and if not it would be more efficient then pile of hacks, that we are creating, very soon.
I long for the day, but hardware with new securiy features takes many years to reach users. And historically, hardware couldn't fully close all the holes either, so that people still use a combination, a pile of different features
Software prevention adds complexity, but it has been very worth it in the mean time. And easy to turn off should the end-all be all hardware capability reach users
And we can very well work towards both! Making attacker lives harder is super positive sum, methinks.
Free software's not-so-eXZellent adventure
Posted Apr 3, 2024 10:01 UTC (Wed) by khim (subscriber, #9252) [Link]
> Those run after relro, so that you can't overwrite the GOT.Of course you can! Lots of games (or, rather, their cheat-protection systems) are doing that. Just call mprotect.
Only as long as regular users don't feel the heat. Recall how long it took for people to accept SELinux and not reflexively turn it off on a new installations to reduce number of support calls.
What you are proposing is significantly more intrusive (if you would also introduce enough hoops to make simple call to mprotect syscall unfeasible) and it's unclear how hard would you need to circumvent all these hoops.
Most mitigation strategies are working on the assumption that malicious code is still severely restricted at what it may do because it vas injected in your process using very “narrow” path (few bytes of buffer overflow, heap-spraying and so on).
Library, on the other hand, is very “wide” path. Trying to make it “narrow” would introduce so many disruptions that we would get the same effects that banks with strict “security teams” are getting: they enforce protocols to dirsuptive and painful that people are just moving data outside of these protocols to ensure that some would would actually be done… and then it leaks (or worse) from there.
Free software's not-so-eXZellent adventure
Posted Apr 3, 2024 10:40 UTC (Wed) by tux3 (subscriber, #101245) [Link]
Please do, that is actually my dream scenario!
I am thinking about writing a detector for strange behavior in new Debian uploads, and an mprotect syscall on plt.got is a super cut-and-dry reason for my detector to flag a package as suspicious =)
If closing the ifunc vector forces attackers to use mprotect() or similar noisy syscalls, I'm counting this as a win, I'd be very happy with that result
>What you are proposing is significantly more intrusive (if you would also introduce enough hoops to make simple call to mprotect syscall unfeasible) and it's unclear how hard would you need to circumvent all these hoops.
I think we should consider separately mitigations that affect everyone (e.g. a new compile flag for a binary to opt-out of the ifunc mechanism, even in any of the libs it loads), and detection efforts.
I'm proposing that we make it hard to do things quietly for everyone, so that attackers make noise.
Then a CI system somewhere, not your computer, can do some heavy instrumentation without impacting regular users
Agree that we can't try to make libraries too 'narrow'. At some point if you run malicious code, you run malicious code. But letting malicious code run during load-time, before relro, in a process that otherwise would never have called liblzma I think is making it too easy for the attackers.
If we have an opt-in to close the really dangerous stealthy attack vectors like ifuncs in sshd, then attackers may have to make noise (e.g. mprotect), and a "run-time linter" might catch them.
Free software's not-so-eXZellent adventure
Posted Apr 3, 2024 11:51 UTC (Wed) by khim (subscriber, #9252) [Link]
> If closing the ifunc vector forces attackers to use mprotect() or similar noisy syscalls, I'm counting this as a win, I'd be very happy with that resultUnlikely, as I wrote already: “closing the ifunc vector” would just lead to proliferation of juicy, ready-to-exploit tables full of function pointers in the unprotected .data segment.
Then you would just need to pick the one you feel is most stable to exploit it.
> e.g. a new compile flag for a binary to opt-out of the ifunc mechanism, even in any of the libs it loadsThat one is 200% impractical for most apps, including ssd. Before you may even contemplate that you first need to move pam mechanism into separate process.
That's entirely impractical: our current OOP-style paradigm relies too much on using vtables. And while function pointer tables are, very often, protected, the actual references to these tables are not.
And fixing that issue is utterly impractical: that's literally the way we have been developing software for last few decades.
Going back to the drawing board and switching to some other development methodology is even harder then creation of a new hardware, this may only happen if we would develop new way to doing things and then wait for a new generation of developers to grow.
> But letting malicious code run during load-time, before relro, in a process that otherwise would never have called liblzma I think is making it too easy for the attackers.Unfortunately it's also something that is used for many fully legitimate purposes.
> If we have an opt-in to close the really dangerous stealthy attack vectors like ifuncs in sshd, then attackers may have to make noise (e.g. mprotect), and a "run-time linter" might catch them.Forget ifunc's! These were just a low-hanging fruit which were easy to exploit, but compared to bazillion vtables embedded everywhere… which are already numerous and which would greatly increase in numbers if you would disable ifuncs…
I'm really glad that no one takes your ideas seriously because in your attempt to play the whack-the-mole game you are proposing solutions which would lead to multiplication of such moles… that's a losing game.
Security is not achieved by replacement of standard solution with bazillion ad-hoc ones, each with its own juice security hole.
Free software's not-so-eXZellent adventure
Posted Apr 3, 2024 16:33 UTC (Wed) by aaronmdjones (subscriber, #119973) [Link]
It wouldn't surprise me if, due to this attack, in the near future we get a linker option (-z foo) that instructs the dynamic linker to extend full RELRO by calling mseal(2) on the GOT and such before invoking any global ctors or main().
I also wouldn't be surprised if OpenBSD is considering doing exactly the same thing for all of their userspace right now; they have an mimmutable(2). If they haven't already.
Free software's not-so-eXZellent adventure
Posted Apr 3, 2024 13:20 UTC (Wed) by farnz (subscriber, #17727) [Link]
It's not just IFUNCs, although they were used in this attack. It's also .init_table, .ctor and other ELF mechanisms intended to run code when an object is loaded.
There are two fundamental design decisions in ELF that were chained to get here:
- Imports of a symbol merely specify the symbol name, and not the library it comes from; I import (for example) EVP_DigestSignInit_ex@OPENSSL_3.0.0, not EVP_DigestSignInit_ex@OPENSSL_3.0.0 from libssl.so.3, let alone EVP_DigestSignInit_ex@OPENSSL_3.0.0 from /usr/lib/libssl.so.3. As a result, if liblzma.so.5 is listed as providing symbols needed to run this binary, it has to be loaded as soon as the binary attempts to use a symbol that's dynamically linked (such as memcpy) in order to determine if the symbol is provided by this library.
- Loading a library implicitly runs code from that library; this exists to make it easy to implement C++ static constructors ("dynamic initialization"), since it allows you to avoid all the fun around "first use of any function or object defined in the same translation unit as the object to be initialized", and instead just do all the dynamic initialization before main, as well as for multi-ABI support (which is what IFUNCs provide).
The first is, I suspect, where a lot of developer confusion comes from (and it's worth noting that Mach-O as used on iOS and macOS has imports specify both a symbol and an expected origin, allowing Darwin's dynamic linker to delay loading a library until an import indicates that it's expecting a symbol to be found in that library).
The second is useful to attackers in general, since it means that if they can get you to load their library (e.g. by dynamically linking against it), they can run their attack code; restricting it would mean that attackers would have to not only get you to load their library, but also to use at least one symbol from their library in order to get code execution.
Free software's not-so-eXZellent adventure
Posted Apr 3, 2024 16:08 UTC (Wed) by draco (subscriber, #1792) [Link]
I don't know if it would've eliminated the possibility of this attack (I need to get around to reading up on how dynamic linking works, I know LWN did an article a few weeks ago), but it feels like with smart use of provenance/capabilities, liblzma would've had no ability to mess with the data structures without the help of the dynamic linker.
But progress on that front seems frustratingly slow. Maybe because too few people are aware of the work
Free software's not-so-eXZellent adventure
Posted Apr 3, 2024 16:43 UTC (Wed) by khim (subscriber, #9252) [Link]
> But progress on that front seems frustratingly slow. Maybe because too few people are aware of the workPeople are aware, as I have said it all goes back to iAPX 432 and PP 250 so more than half-century old by now.
But as it turned out people are not ready to pay for security, they expect to obtain it for free, somehow. And when I mean “pay” here I mean “pay with convenience”, not money.
I still remember how data security company tried to, somehow, sell it's warez in US. The first thing US marketing guys demanded is to neuter base security restrictions and remove mandatory pin use from the device!
And to this day all devices that we developing are made for convenience first, security second… and it's not clear if we may change that without civilizational collapse. Otherwise people wouldn't even think about exchanging convenience for security.
Flat address space, ifuncs and other such things are only sympthoms.
Free software's not-so-eXZellent adventure
Posted Apr 2, 2024 21:59 UTC (Tue) by khim (subscriber, #9252) [Link]
> If any library that is transitively linked into an executable can override any function in the executableWhich is, of course, possible on majority of OSes (not 100% about OpenBSD, there are some mitigations in place which would require certain amount of non-trivial dance to achieve that, but I think it's possible even there).
> then the intuition of most programmers is going to be wrong.Maybe we should fix the intuition, then?
Libraries are injected into the address space of the same process. They inherently may do “everything” in that process, including, but not limited to the rewrite of the code of other libraries (or binary). You may play cat-and-mouse game with trying to plug these holes, but that protection would never be water-tight, it's not not a security boundary in a normal process. By design.
Sure, we may recall ideas of iAPX423/e2k/CHERI, but I wouldn't expect these to become a mainstream any time soon and till that would happen changing the intuition is the only possible interim solution.
Free software's not-so-eXZellent adventure
Posted Apr 3, 2024 6:16 UTC (Wed) by tux3 (subscriber, #101245) [Link]
We don't even need to close all the holes. Just the ones that are cheap and hard to detect.
A CI system somewhere sending an email because sshd in Debian sid is seen doing weird .text overwrite at load time? This also catches the mouse.
If you can't outrun them, force 'em to do crazy things that no normal free software package does, so that we have a chance to detect it.
Without ifuncs, I think they'd have had a much harder time making this stealthy. And for a backdoor that was detected because it disturbed a microbenchmark, stealth is everything!
Free software's not-so-eXZellent adventure
Posted Apr 3, 2024 11:22 UTC (Wed) by khim (subscriber, #9252) [Link]
> Without ifuncs, I think they'd have had a much harder time making this stealthy.Without ifuncs they would just need to play with internal sshd data structures to find any suitable function pointer they may overwrite.
And without ifuncs there would be many more such pointers, because the need to have extra-fast `memcpy` wouldn't go away without ifuncs. Only instead of mostly-protected GOT these redirectors would be placed in regular data segment.
> And for a backdoor that was detected because it disturbed a microbenchmark, stealth is everything!I'm not all that sure the end result would reduction in the attack surface and would actually suspect it would actually increase it.
If you remove central CPUID-support mechanism then you are forcing people to invent their own, ad-hoc ones. History says that usually this leads to negative impact on security, not positive one: instead of one, central mechanism which can be monitored for doing something unusual you are getting hundreds of ad-hock implementations.
You may find the example here (it's bionic, yes, but that's part which existed before they added support for ifunc's). It's a bit harder to [ab]use today, it used to have ready-to-use-GOT-replacement for most malloc-related functions.
And because crypto-routines are very speed-conscious (different CPUs offer different ways to improve them) chances are high that without ifuncs there would tons of easy-to-rewrite function pointer tables.
Doesn't work if you also force free software packages to do crazy things that add more entry points for malicious actors. Your attempt to neuter ifuncs would do just that.
Free software's not-so-eXZellent adventure
Posted Apr 3, 2024 7:53 UTC (Wed) by epa (subscriber, #39769) [Link]
Free software's not-so-eXZellent adventure
Posted Apr 3, 2024 10:48 UTC (Wed) by farnz (subscriber, #17727) [Link]
Actually fixing that edge case is going to be extremely hard. ELF has chosen to enable compilers to implement C++ dynamic initialization (for statics) as running code before main starts (via the .init_array section), which means that loading a library is enough to run code from that library.
While it is, per the standard, permissible to reimplement this so that dynamic initialization is deferred until first use of a symbol, that's a significant change to current C++ compilers (including GCC and Clang), and is likely (for efficiency reasons) to need changes to ELF so that the dynamic linker can determine whether this is the "first use" of a symbol and run the initializer at this point, rather than at program startup.
This is a behaviour change that will surprise quite a few people - there will be C++ programs that expect side-effects of globals to be run before main - but it's a major blocker to preventing a malicious library from running code just because it's linked.
Free software's not-so-eXZellent adventure
Posted Apr 2, 2024 22:06 UTC (Tue) by AlecTavi (subscriber, #86342) [Link]
This was particularly clever subterfuge. I read the linked commit diff on my phone, and missed how this disabled Landlock. I even copied the C source to check if there was some typo in a syscall I didn't notice from memory. Still, everything compiled and looked legitimate.
If others miss it too, there's a stray period in the diff. My eyes skipped right over it. When I deleted the diff formatting from the code, I removed the period and had a legitimate C file.
Free software's not-so-eXZellent adventure
Posted Apr 2, 2024 23:07 UTC (Tue) by rrolls (subscriber, #151126) [Link]
What I'm curious about is: why does a file with a syntax error in it cause something to get silently disabled, rather than failing the build?
Free software's not-so-eXZellent adventure
Posted Apr 2, 2024 23:32 UTC (Tue) by viro (subscriber, #7872) [Link]
defined in foo.h or is it in foo/bar.h"?
Look through the autoconf tests done on some build...
Free software's not-so-eXZellent adventure
Posted Apr 2, 2024 23:33 UTC (Tue) by mjg59 (subscriber, #23239) [Link]
Free software's not-so-eXZellent adventure
Posted Apr 2, 2024 23:47 UTC (Tue) by hmanning77 (subscriber, #160992) [Link]
The issue is that there are apparently cases where the only reliable way to detect the presence or absence of a feature is to try to compile it. When the check fails in a single environment there is no automatic way to know whether the code failed to compile on that machine, or could never have compiled at all. The issue tracker discussion immediately dismisses the general problem as impossible to solve, and diverts to catching the easiest avenues for abuse.
I don't have any better ideas to offer though. I'm assuming it isn't feasible to say, "security features should be enabled by default as best practice and never automatically disabled". The root cause is that discovering available features is hard; could that be improved?
Free software's not-so-eXZellent adventure
Posted Apr 2, 2024 23:51 UTC (Tue) by excors (subscriber, #95769) [Link]
Free software's not-so-eXZellent adventure
Posted Apr 3, 2024 5:48 UTC (Wed) by chris_se (subscriber, #99706) [Link]
One possibility could be that the original plan was to perform various changes that themselves were very innocuous-looking over a longer period of time, and that the end goal was to also backdoor the CMake build. (Maybe in a different manner, because the CMake build is used more in conjunction with vendor-distributed software, e.g. via conan, vcpkg, etc.) But that for some reason the timeline moved up and they had to pull the trigger early. (It has already been speculated that the systemd change to use dlopen() in the future may have forced the hand.) Or their intention was to also break the autotools variant, and they simply messed up by forgetting to add the dot to that check accidentally.
But unless the culprit(s) come(s) forward, we'll probably never know the reasoning behind it.
> (Or maybe it really was just a fat-finger; malicious people can still make innocent mistakes.)
Or this. Since they put in so much effort to actually seem legitimate as part of the social engineering, this may have also been an attempt to simply fix a legitimate issue properly that went wrong accidentally.
People have gone through all commits by the same author, and they have found a lot of things that with hindsight could be seen as malicious, but for some of these we'll probably never know whether they were very clever in attempting to introduce very subtle bugs, or they simple made honest mistakes and those commits were actually intended to just be part of the social engineering aspect to seem legitimate.
That said, since they have been shown to be an adversary, we should consider all subtle bugs to be of malicious intent out of an abundance of caution, even if on a philosophical level we'll probably never know the actual truth of that.
Free software's not-so-eXZellent adventure
Posted Apr 3, 2024 15:42 UTC (Wed) by draco (subscriber, #1792) [Link]
Easier to explain away one typo than two…
Free software's not-so-eXZellent adventure
Posted Apr 2, 2024 23:13 UTC (Tue) by Cyberax (✭ supporter ✭, #52523) [Link]
It can legitimately be just one individual acting on their own. And there is a pretty solid motivation for it: cryptocurrency. These days, if you manage to sneak a backdoor into something like SSH, you can quite easily leverage that for an immediate payoff on the hundred-million dollar scale. No need to deal with stingy government agencies (that can "disappear" you just as well as pay you off).
Free software's not-so-eXZellent adventure
Posted Apr 3, 2024 18:12 UTC (Wed) by lunaryorn (subscriber, #111088) [Link]
Kinda reminds me of the event-stream incident in 2018… this "hostile contributor takes over" move had a precedent.
Free software's not-so-eXZellent adventure
Posted Apr 3, 2024 8:36 UTC (Wed) by stephanlachnit (subscriber, #151361) [Link]
Such a good point IMHO. Yes, using a different build system could have resulted in the same thing, but autoconf is such a mess that almost nobody looks inside the scripts except if they have to. E.g. Meson+Python is not just easier to read for beginners, most people also know at least a little bit of Python to see what is going on.
autoconf really has to go, it's time as the main build system for core components is long over.
Free software's not-so-eXZellent adventure
Posted Apr 3, 2024 9:58 UTC (Wed) by nsheed (subscriber, #5151) [Link]
By itself it's an incredibly clever hack but the surrounding effort involved in planning and then shepherding/protecting the various parts through to fruition is scary.
Free software's not-so-eXZellent adventure
Posted Apr 3, 2024 11:33 UTC (Wed) by khim (subscriber, #9252) [Link]
That's why I don't believe for a minute that “Jia Tan” is a free actor. $THREE_LETTER_AGENCY is definitely involved (I wish we knows which one), simply because there was obviously a lot of efforts to plan that.
We only see a top of an iceberg, but that was definitely well-timed and coordinated to make literally tons of distributions vulnerable in the near future… and lone hackers in the basements are not know for such level of coordination while for three letter agencies that's routine scale level of coordination.
