Forgot your password?
typodupeerror
Security Unix Technology

Arbitrary Code Execution With "ldd" 184

Posted by kdawson
from the so-easy dept.
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."
This discussion has been archived. No new comments can be posted.

Arbitrary Code Execution With "ldd"

Comments Filter:
  • ldd pwned (Score:2, Funny)

    by Anonymous Coward
    Sounds like someone needs to make LDD not capable of executing arbitrary code then =] /captainobvious
    • by postbigbang (761081) on Monday October 26, 2009 @11:24AM (#29872879)

      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....

    • by FranTaylor (164577) on Monday October 26, 2009 @11:24AM (#29872887)

      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)

        by Anonymous Coward

        So our lesson here is... don't run any scripts we don't fully understand as root. Thanks Slashdot - I feel so informed today!

      • by Skapare (16644) on Monday October 26, 2009 @11:42AM (#29873087) Homepage

        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).

        • by corbettw (214229)

          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.

      • by Timothy Brownawell (627747) <tbrownaw@prjek.net> on Monday October 26, 2009 @11:46AM (#29873149) Homepage Journal

        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.

        • by marcansoft (727665) <hector@mar c a nsoft.com> on Monday October 26, 2009 @01:22PM (#29874373) Homepage

          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 that we're running a compromised executable. Once someone can get that into the system, it's over. Now it sounds like ldd is being used here possibly for increased privileges, but that's all. The real challenge is getting someone a compromised executable.
          • Re: (Score:3, Informative)

            There's different ways of getting compromised executables onto systems. They're just files, after all, and lots of systems have ways of accepting arbitrary files (FTP servers, for example, often have anonymous dropboxes). The trick is to get somebody to execute them, and most people running Linux systems are a bit smarter than that. If the admins think a certain thing is harmless, and it isn't (in this case, ldd), it's an attack vector.
            • by nullchar (446050)

              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.)

      • by makomk (752139)

        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)

      by Skapare (16644) on Monday October 26, 2009 @11:27AM (#29872913) Homepage

      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)

        by sjames (1099)

        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.

        • by Tanktalus (794810)

          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).

          • by sjames (1099)

            If the loader is suid root, then anyone can become root with /lib/ld*.so /bin/bash

            • by Tanktalus (794810)

              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.

              • by sjames (1099)

                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?

        • by Carewolf (581105)

          The easiest think would be to not use ldd and use "readelf -d" instead

          • by sjames (1099)

            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.

            • where the library exists but ld.so.conf doesn't know it or where several variations exist but not the right one.

              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).

  • Fetch me my tinfoil hat!

  • by MyLongNickName (822545) on Monday October 26, 2009 @11:25AM (#29872895) Journal

    In Windows, we avoid this vulnerability by giving you absolutely no fricking clue what dependencies exist for any given DLL. Suck that Unix fanboys!

      • by MyLongNickName (822545) on Monday October 26, 2009 @11:30AM (#29872949) Journal

        Yup. I've used it. It is a very useful tool. Note that this is not something built into Windows.

        • 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:2, Insightful)

      by Anonymous Coward

      depends.exe. Doesn't execute arbitrary code either.

      ldd is a hack and always has been. It's really just a special "run mode".

    • by joebp (528430) on Monday October 26, 2009 @11:31AM (#29872955) Homepage
      depends.exe does exactly this and ships with the platform sdk.
    • ...I'm sure someone will find some other vulnerability.

  • Thorough research (Score:5, Insightful)

    by Mortice (467747) on Monday October 26, 2009 @11:32AM (#29872963)

    '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.

    • by pkrumins (720890)
      That's what I mean by "almost." This is just a warning. It was this warning that got me excited to research more on this topic.
      • Re: (Score:3, Insightful)

        by pkrumins (720890)
        What I mean is that I found only 3 or 4 references to this problem on the whole Internet. If that doesn't mean *almost completely undocumented* then I don't know what does.
        • by smoker2 (750216)
          If it's documented, then no matter how many superlatives you use, your statement is wrong. If I write a program and release it with documentation available on my web site, would you say that it was "almost completely undocumented " ?

          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)

            by Random Walk (252043)
            The Linux manpage (on Ubuntu 8.04) says ldd prints the shared libraries required by each program or shared library specified on the command line. Note that it doesn't mention anywhere that the program is executed, and doesn't contain any security warning. If there is no hint of the problem at the primary source of usage information, then the issue IS undocumented.
    • Re:Thorough research (Score:5, Interesting)

      by marcansoft (727665) <hector@mar c a nsoft.com> on Monday October 26, 2009 @01:29PM (#29874481) Homepage

      One wonders why no one thought to add that to the manpage.

    • Re: (Score:3, Interesting)

      by Omnifarious (11933) *

      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.

      • Your assumptions were wrong. And this is a design flaw in ldd?
        • 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.

  • 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.

  • Cool and so what (Score:4, Insightful)

    by nweaver (113078) on Monday October 26, 2009 @11:32AM (#29872969) Homepage

    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

    • by Lord Bitman (95493) on Monday October 26, 2009 @11:48AM (#29873175) Homepage

      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

      • by the 99th penguin (1453) on Monday October 26, 2009 @11:58AM (#29873327) Journal

        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?

      • 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)

        by Nevyn (5505) *

        SELinux has this capability: http://danwalsh.livejournal.com/28545.html [livejournal.com]

        • 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.

      • by Greyfox (87712)
        There are virtual machines, but they're much more of a bother to set up than running a simple command like that. UNIX also has the concept of a chroot jail, but it's a lot more of a bother to set up and not completely safe anyway. I used to audit code for DGUX secure, which had some very hard-core MAC/DAC capabilities. In theory at least you could set "sandbox" up to drop almost all privs on the system prior to executing a piece of code. If you had full logging turned on in that system, "ls" would generate
      • Re: (Score:3, Interesting)

        by sydneyfong (410107)

        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

    • by mi (197448)

      How many cases occur where even with social engineering will someone run ldd but not run the executable?

      Actually, this is one scenario:

      1. send a user (perhaps, via spam) the evil binary (dancing_bunnies);
      2. they'll save it, try to run it, and it will (bogusly) complain about a missing library or two;
      3. the user might then ask their admin for assistance — forwarding him the error message even;
      4. there is a good chance, that the admin will try to use ldd to resolve the missing-library problem.
      5. it is very likely, th
  • 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

  • Nasty (Score:5, Interesting)

    by FranTaylor (164577) on Monday October 26, 2009 @11:34AM (#29872997)

    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)

    by alcourt (198386) on Monday October 26, 2009 @11:38AM (#29873039)

    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.

    • by causality (777677)

      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)

      by nextekcarl (1402899)

      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.

      • by timeOday (582209)

        From what I can tell, you can't really fix this as it is what the program does (though I could be wrong).

        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)

      by theCoder (23772)

      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)

        by Anonymous Coward

        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)

      by TorKlingberg (599697)

      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)

    by Thunderstruck (210399) on Monday October 26, 2009 @11:44AM (#29873117)

    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!"

  • by HaloZero (610207) <protodeka AT gmail DOT com> on Monday October 26, 2009 @11:46AM (#29873147) Homepage

    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!

  • Other dirty tricks (Score:5, Interesting)

    by sjames (1099) on Monday October 26, 2009 @11:55AM (#29873289) Homepage

    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.

  • 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?"

    • by hey (83763)

      Good point.

    • by Tetsujin (103070)

      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

  • by Siberwulf (921893)
    Uh, yeah. Godmode ftw. Who else didn't see this coming?
  • Rename it! (Score:4, Funny)

    by mweather (1089505) on Monday October 26, 2009 @12:40PM (#29873807)
    They should rename it iddqd in honour of this new feature.
  • 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"

  • ... but not much else. The potential code-execution is a surprising behavior, that nonetheless is not that critical.

  • So what? (Score:3, Insightful)

    by ledow (319597) on Monday October 26, 2009 @01:50PM (#29874729) Homepage

    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.

  • by dwheeler (321049) on Monday October 26, 2009 @02:26PM (#29875213) Homepage Journal
    This is documented, and in multiple places. My Program Library HOWTO, section "Shared Libraries" [dwheeler.com], says the following, and it's dated in 2000: "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." Now I'd agree that it would better if ldd were changed to NOT do this. If the result of this article is a change in its code to not do this, that would be a great result. But it's simply not true that this is undocumented.
  • 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.

  • and I mainly use Windows these days...but this seems like a none issue. If someone can get their executable on your system, I'm sure that they can come up with a better way of running it than having you ldd it. I mean, the fact that it's there means that you've downloaded untrustworthy software and are probably just going to run whatever it is anyway, and probably as root if it asks for it.

If I have not seen so far it is because I stood in giant's footsteps.

Working...