Live data from Hacker News

Xz/liblzma: Bash-stage Obfuscation Explained

gynvael.coldwind.pl

51–60 of 137 posts

Re: Xz/liblzma: Bash-stage Obfuscation Explained

#51
post #27

Earlier quoted context omitted.

In addition… if your build system has things like this as OK: > xz -dc $top_srcdir/tests/files/$p | eval $i | LC_ALL=C sed "s/\(.\)/\1\n/g" | LC_ALL=C awk 'BEGIN{FS="\n";RS="\n";ORS="";m=256;for(i=0;i You should probably expect the potential for abuse? We’re moving towards complexity that is outpacing human ability for any one person to understand, explain, and thus check an entire object. And for what? Build efficie…

I’m not sure why you’d say that we’re “moving towards” this sort of build system complexity. This is 1990s autoconf bs that has not yet been excised from the Linux ecosystem. Every modern build system, even the really obtuse ones, are less insane than autoconf. And the original purpose of this was not for efficiency, but to support a huge variety of target OSes/distros/architectures, most of which are no longer used…

> has not yet been excised from the Linux ecosystem

That is my point. I should have written allows and not has.

Re: Xz/liblzma: Bash-stage Obfuscation Explained

#52
post #35

Earlier quoted context omitted.

You do realize that "that shit" was part of the obfuscated and xz-compressed backdoor hidden as binary test file, right? It was never committed in plain sight. You can go to https://git.tukaani.org/xz.git and look at the commits yourself – while the commits of the attacker are not prime examples of "good commits", they don't have glaringly obvious red flags either. This backdoor was very sophisticated and well-hidden…

> It was never committed in plain sight. It was though. I have seen those two test files being added by a commit on GitHub. Unfortunately it has been disabled by now, so I cannot give you a working link.

It really wasn't, though.

    commit 74b138d2a6529f2c07729d7c77b1725a8e8b16f1
    Author: Jia Tan 
    Date:   Sat Mar 9 10:18:29 2024 +0800
    
        Tests: Update two test files.
        
        The original files were generated with random local to my machine.
        To better reproduce these files in the future, a constant seed was used
    to recreate these files.



    diff --git a/tests/files/bad-3-corrupt_lzma2.xz b/tests/files/bad-3-corrupt_lzma2.xz
    index 926f95b0..f9ec69a2 100644
    Binary files a/tests/files/bad-3-corrupt_lzma2.xz and b/tests/files/bad-3-corrupt_lzma2.xz differ
    diff --git a/tests/files/good-large_compressed.lzma b/tests/files/good-large_compressed.lzma
    index 8450fea8..878991f3 100644
    Binary files a/tests/files/good-large_compressed.lzma and b/tests/files/good-large_compressed.lzma differ
Would you bat an eye at this? If it were from a trusted developer and the code was part of a test case?

If you looked at strings contained within the bad file, you might notice that this was not random:

    7zXZ
    ####Hello####
    7zXZ
    w,( 
    7zXZ
    ####World####
But, again, this was a test case.

Re: Xz/liblzma: Bash-stage Obfuscation Explained

#54
can we start considering binary files committed to a repo, even as data for tests, to be a huge red flag, and that the binary files themselves should instead, to the greatest extent possible, be generated at testing time by source code that's stated as reviewable cleartext (though I think this might be very difficult for some situations). This would make it much harder (though of course we can never really say "impossible") to embed a substantial payload in this way.

when binary files are part of a test suite, they are typically trying to illustrate some element of the program being tested, in this case a file that was incorrectly xz-encoded. Binary files like these weren't typed by hand, they will always ultimately come from something plaintext source, modulo whatever "real world" data came in, like randomly generated numbers, audio or visual data, etc.

Here's an example! My own SQLAlchemy repository has a few binary files in it! https://github.com/sqlalchemy/sqlalchemy/blob/main/test/bina... oh noes. Why are those files there? well in this case I just wanted to test that I can send large binary BLOBs into the database driver and I was lazy. This is actually pretty dumb, the two binary files here add 35K of useless crap to the source, and I could just as easily generate this binary data on the fly using a two liner that spits out random bytes. Anyone could see that two liner and know that it isn't embedding a malicious payload.

If I wanted to generate a poorly formed .xz file, I'd illustrate source code that generates random data, runs it through .xz, then applies "corruption" to it, like zeroing out the high bit of every byte. The process by which this occurs would be all reviewable in source code.

Where I might be totally off here is if you're an image processing library and you want to test filters on an image, and you have the "before" and "after" images, or something similar for audio information, or other scientifically-generated real world datapoints that have some known meaning. That might be difficult to generate programmatically, and I guess even if said data were valid, payloads could be applied steganographically. So I don't know! But just like nobody would ever accept a PR that has a "curl https://some_rando_url/myfile.zip" inside of it, we should not accept PRs that have non-cleartext binary data in them, or package them, without really vetting the contents of those binary files. The simple presence of a binary file in a PR can certainly be highlighted, github could put a huge red banner BINARY FILES IN THIS PR.

Downstream packagers for distros like Debian, Redhat etc. would ideally be similarly skeptical of new binary files that appear in the source downloads, and tooling can be applied to highlight the appearance of such files. Packagers would be on the hook to confirm the source of these binary files, or ensure they are deleted (even disabling tests if necessary) before the build process is performed.

Re: Xz/liblzma: Bash-stage Obfuscation Explained

#55

Earlier quoted context omitted.

No, as far as I understand the binary files must be pointed at here: '$gl_am_configmake' ... But I don't see how. This: 'gl_am_configmake=`grep -aErls "#{4}[[:alnum:]]{5}#{4}$" $srcdir/`' seem to match the '####Hello####', but, as far as I can see, that's supposed to be the already converted script?! I presumed the binary files not to contain human readable strings, maybe that's the whole confusion.

Opening bad-3-corrupt_lzma2.xz in an editor reveals it indeed has the string ####Hello####. I don't know enough about lzma compression streams to explain how this appears in the "compressed" version of the payload, but it does.

> I don't know enough about lzma compression streams to explain how this appears in the "compressed" version of the payload, but it does.

From what I've read, the payload isn't stored in the archive, but rather the test file itself is a sandwich of xz data and payload: There are 1024 bytes of xz archive, N bytes of payload, another 1024 of xz, etc.

Re: Xz/liblzma: Bash-stage Obfuscation Explained

#56
post #32

Earlier quoted context omitted.

To be clear: the build system did not use the code fragment you quoted. This complex awk code is a later stage of the backdoor.

I see, my point was more than this shouldn’t be allowed. I think part of the problem with a lot of things is we’re allowing complexity for the sake of complexity. No one has simplicity-required checks. My previous post should say “allows things like this”.

Unless I’m misunderstanding, all this code was embedded and hidden inside the obfuscated test files.

None of this would have been visible in commits or diffs at all.

Re: Xz/liblzma: Bash-stage Obfuscation Explained

#57

Earlier quoted context omitted.

> It was never committed in plain sight. It was though. I have seen those two test files being added by a commit on GitHub. Unfortunately it has been disabled by now, so I cannot give you a working link.

It really wasn't, though. commit 74b138d2a6529f2c07729d7c77b1725a8e8b16f1 Author: Jia Tan Date: Sat Mar 9 10:18:29 2024 +0800 Tests: Update two test files. The original files were generated with random local to my machine. To better reproduce these files in the future, a constant seed was used to recreate these files. diff --git a/tests/files/bad-3-corrupt_lzma2.xz b/tests/files/bad-3-corrupt_lzma2.xz index 926f95b0.…

> Would you bat an eye at this? If it were from a trusted developer and the code was part of a test case?

well lets all agree that now, if we see commits affecting / adding binary data with "this was generated locally with XYZ", that now we will bat an eye at it.

Re: Xz/liblzma: Bash-stage Obfuscation Explained

#58

Thanks the simplified explanation and noisy image comparison is quite appreciated. It gives me a good grasp of what people mean by the sophistication involved. I also saw a comment on reddit mentioning that the "sandboxing" method was sabotaged with a dot. It's on the line just after "#include " you can see a dot all the way on the left. https://git.tukaani.org/?p=xz.git;a=commitdiff;h=328c52da8a2... https://old.redd…

This is very likely just a mistake and not deliberate.

a) absolutely nobody uses cmake to build this packet

b) if you try to build the packet with cmake and -DENABLE_SANDBOX=landlock, the build just fails: https://i.imgur.com/7xbeWFx.png

The "." does not disable sandboxing, it just makes it impossible to build with cmake. If anyone had ever actually tried building it with cmake, they would get the error and realize that something is wrong. It makes absolutely no sense that this would be malicious attempt to reduce security.

Re: Xz/liblzma: Bash-stage Obfuscation Explained

#60
i don’t have a better answer, but this convoluted mess of bash is a smell isn’t it?

i live in a different part of the dev world, but could this be written to be less obtuse so it’s more obvious what’s happening?

i get that a maintainer can still get malicious code in without the same rigor as an unaffiliated contributor, but surely there’s a better way than piles of “concise” (inadvertently obfuscated?) code?

Post reply on HN