6 ms·
I Built an Ld_preload Worm
- buildbot 3y agoIsn’t this still actually wormable to some degree? Just among system you have access too. But imagine if any of those at all are shared…
- theamk 3y agoThis can only propagate to other users if you are superuser on host and used "sudo". So yes, they will definitely propagate for a bit, but they won't go very far unless it's a very unusual environment.
- buildbot 3y agoShared lab machines come to mind! Often many people have sudo and sometimes there is just one shared account.
- fullspectrumdev 3y agoWith some additional tricks, lab machines at universities would be fertile soil for such.
- theamk 3y agoDo people actually have lab machines with shared accounts and everyone having sudo access? This sounds horrifying.. students do want to experiment, and it's enough for a single person to install gcc-5 as system compiler to ruin everyone's day. Surely the sysadmins are doing something to prevent this? Like NFS root or at least "no sudo access" by default?
- buildbot 3y agoGood point,, in school the undergrad lab machines where very locked down and secure. In grad school, every prof had their own few machines in the lab that where shared, limited sudo access to me, I'm sure some shared the machines more openly. At work though, our lab machines that are not cloud based are shared across the team, everyone has sudo. They get broken all the time whenever someone decides they need a different cuda version. I've brought it up as an issue but nobody really cares haha.
- cryptonector 3y agoTFA's unicorns.so would still work today.
- fullspectrumdev 3y agoYes. https://thc.org/ssh-it/ https://thc.org/ssh-it/ being a more recent implementation of the same concept, using $PATH modification instead of LD_PRELOAD. It also has some other optional tricks such as searching for unprotected SSH keys and the likes. This kind of thing can be deeply interesting to run in environments where developers share things like jump boxes, to determine the “blast radius” of a compromised account over time as part of a security exercise.
- kibwen 3y agoThe xz debacle made me keenly aware of what a weak point the linker is, and now I kinda want a system that doesn't have a dynamic linker at all.
- klysm 3y agoI’ve been convinced static linking is the way to go for a number of years. The benefits of dynamic linking don’t make sense anymore imo
- intelVISA 3y agoAwoken
- tssge 3y agoOn single user systems, sure. However multi user systems can benefit greatly from dynamic linking; some highly multi user systems become impossible to create at all with only static linking (RAM demand becomes too great). Dynamic linking also leads to better CPU cache utilization and thus higher performance; provided if multiple applications are actually utilizing the dynamically linked library. While RAM is somewhat abundant these days, L1/L2/L3 cache on your CPU most definitely isn't. Application startup times are also of higher performance when part of the code is already in memory. EDIT: Let me elaborate a bit on what I mean by "benefiting greatly" with a real world example. I have a system with around 300 tenants with a minimum of 500 PHP processes online at any given time. A single PHP process is able to load 70MB worth of dynamically linked libraries (PHP extensions) if so chosen by the tenant. I'll just skip libc and other such libraries to give static linking a chance. With dynamic linking, the maximum memory requirement is 70MB for said extensions. With static linking, the maximum memory requirement is 35GB for said extensions. Dynamic linking thus leads to 99,8% cost saving on memory usage. Bear in mind this is at minimum load: static linking requirements will scale linearly with load. Not to even get started on the performance benefits this brings...
- gpm 3y agoAre these extensions standard across your users, or are they user supplied? If the former is the case, in a world where dynamic linking wasn't "the way things were done", you'd just just statically link them all into the PHP interpreters binary, and then only run the code to actually start them for the users that want them. Linux shares memory between the different instances of the same executable the same way it does between different instances of a shared library, there should be no difference in cost. Today, I doubt php supports this, particularly the "only run the code to actually start them" part, but in principle it's a lot simpler than dynamic linking to do that. If the latter is the case, how are you getting any savings today?
- timtzm 3y agoI still want dynamic linking, but only a few trusted library files would be allowed to make system calls. Like libc. Sorry but golang would have to change to use libc. This breaks the ABI, but it breaks it for naughty programs the most.
- jiveturkey 3y agoI'm not sure how it's relevant exactly to TFA. The mechanism of propagation is an existing feature of libdl that uses an environment variable. With this worm, the loader still runs exactly as before, from libc and libdl. As to restricting syscalls from certain calling libraries, macOS has this via entitlements, and I believe OpenBSD and/or NetBSD has this in some form as well.
- saagarjha 3y agoEntitlements cannot protect against things in your own process. They are always used to gate clients either across a kernel-user or XPC boundary.
- jiveturkey 3y agoisn't that exactly what the parent was asking for? limiting syscalls. EDIT: oh. but not limited to the caller from a specific system library.
- saagarjha 3y agoOpenBSD does this; it’s not very useful unless you have strong CFI to prevent people from doing a return-oriented attack into those libraries that are in your address space. And also note that there is a lot that you can without system calls to mess with stuff :)
- jdsalaro 3y ago> CFI They're referring to Control Flow Integrity [1] [1] https://en.m.wikipedia.org/wiki/Control-flow_integrity https://en.m.wikipedia.org/wiki/Control-flow_integrity
- theamk 3y agoThis is a nice POC, but would be detected pretty fast in "real world". That "printf" hiding hook seems to be specifically tailored to one command (bash's "set"? "env"?). Any other command to look at environment which does not use printf would show LD_PRELOAD just fine. I, for example, routinely use "strings" to examine environ of desktop processes - try intercepting that. There is also sorted(os.environ.keys()) from Python, and env dump at the start of CI jobs... Not to mention that even if variable itself is perfectly hidden, the preload action itself is visible. LD_PRELOAD-ed libraries show up in "ldd" output, and in "strace" output as well, and in "gdb" outputs. The "propagation" part is just appending to ~/.bash_profile, which is trivially discoverable as well. You can "cat" the file and it'd be right there, or if you have some sort of VCS for you dotfiles, they will flag file as having been changed. With enough imagination, you can figure a way to bypass most of those detection method.. but that "most" is not going to be enough. In the hypothetical example of xz-like attack, you only need one slip-up for such worm to be quickly detected, brought to light, and countermeasures brought up. (targeted attacks are much scarier, but they aren't likely to use such a crude method anyway... even PATH mangling is more subtle that that!)
- wolfendin 3y agoThe real world of 2024, or the real world when this software was written?
- theamk 3y agoGood point actually, the article says "late 1990's".. but most things would still work back then. I believe ldd, strace, procfs all existed back then. Python would not, but one could dump environment using perl or some unusual shell. Keeping dotfiles in version control was be much more rare, so that detection method would not work back then. But the shell variety was much greater back then, so the worm could end up on server with tcsh or ksh or rsh (the "restricted shell") which would render it inert. And there was a chance of ending up on Solaris box which would just throw errors about wrong architecture and cause immediate discovery. Also, there were many more shared systems, so granting "sudo" access to everyone was much less frequent back then. And we could have friendly sysadmins examine someone's configs file if they ask for help, which would lead to discovery as well.
- lukaszwojtow 3y agoOld lcamtuf is back!
- loa_in_ 3y agoNot that they ever went anywhere.
- mfreeman451 3y ago[dead]
- TheAdamist 3y agoLD_AUDIT is even more interesting, and lesser known. It will load even before preload, and has handy hooks for everything that the loader does. https://man7.org/linux/man-pages/man7/rtld-audit.7.html https://man7.org/linux/man-pages/man7/rtld-audit.7.html And had some nasty easy to exploit privilege escalation problems a while ago, https://cve.mitre.org/cgi-bin/cvename.cgi?name=cve-2010-3847 https://cve.mitre.org/cgi-bin/cvename.cgi?name=cve-2010-3847
- aidenn0 3y agoThere's something poetic when information about an environment-variable vulnerability being served over a CGI script...
- nottorp 3y ago> My motivation for this code was to demonstrate the fragility of... Yeah right. I wrote a simple .com infecting virus back when DOS was all the rage. Just to see how it's done. Didn't need any fancy motivational stuff. Never extended it to exes and never distributed it.