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."
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.
Re:ldd pwned (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.
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:Cool and so what (Score:3, Interesting)
SELinux has this capability: http://danwalsh.livejournal.com/28545.html [livejournal.com]
Re:Thorough research (Score:5, Interesting)
One wonders why no one thought to add that to the manpage.
Re:Cool and so what (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 anonymous users while keeping the machine safe. Most slashdotters would call me crazy but this [wikipedia.org] was what I was trying to do at the time.
I'm no security expert, but from what I gather this scheme is pretty safe if you trust the kernel to be free of exploits (particularly in the whitelisted syscalls).
I'm pretty sure a "sandbox" command could be done using ptrace. In fact if you google for "ptrace" you'll find some sites going into a bit of detail how this could be implemented.
In fact I suspect that a patch to strace (which uses ptrace as its underlying syscall tracking mechanism) could deal with the problem if only in a hackish manner.
Re:Thorough research (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.
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 dependencies: when followed as a convention in a friendly environment, this is fine... In a potentially hostile environment this could be a real problem. To solve it without fundamentally changing how "ldd" works requires either education (helping people to recognize the dangers and limitations of "ldd") or else protected-environment facilities, like process jails. (If "ldd", functioning as it does, were run such that it couldn't open network connections, couldn't write to the disk, etc. then there'd be little danger of an exploit...)
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.
This boils down to relying upon "someone else" to do the work and provide me with the useful information that results from the process... The problem with that is that most other folks are also relying upon "someone else" to do this work...
Don't get me wrong, I agree with the principle of having this information out in the open. But in this case, pragmatically speaking, this appears not to have accomplished anything. How long has this problem existed? How long have people known about this? (For quite a while, it seems...) And still, there is barely even a trace of a mention of it in the manual. "Don't use this on code you don't trust" would be quite a prudent addition, I think...
Given that this issue (I hesitate to call it a "bug" - you could think of it as a bug, but it's kind of fundamental to the way ldd works... I think of it more as a fundamental miscommunication of ldd's applicability) has been around so long and hasn't been fixed, isn't mentioned in the docs, etc., I would say any complains about the Windows equivalent being closed source are rather silly in this case: the open model hasn't worked better here.