Slashdot Mirror


Arbitrary Code Execution With "ldd"

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

53 of 184 comments (clear)

  1. ldd pwned by Anonymous Coward · · Score: 2, Funny

    Sounds like someone needs to make LDD not capable of executing arbitrary code then =] /captainobvious

    1. Re:ldd pwned by postbigbang · · 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....

      --
      ---- Teach Peace. It's Cheaper Than War.
    2. Re:ldd pwned by Skapare · · Score: 4, 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").

      --
      now we need to go OSS in diesel cars
    3. Re:ldd pwned by sjames · · Score: 2, 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.

  2. Quickly! by Drunken+Buddhist · · Score: 2, Funny

    Fetch me my tinfoil hat!

    --
    -1, Disagree is not a valid option. Troll, Flamebait and Offtopic are not a substitute.
  3. the bug is not in ldd by FranTaylor · · Score: 3, Informative

    If you had read the article closely you would understand that the bug is not in ldd, it is in the dynamic loader.

    1. Re:the bug is not in ldd by Anonymous Coward · · 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!

    2. Re:the bug is not in ldd by Timothy+Brownawell · · Score: 3, 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.

    3. Re:the bug is not in ldd by evanbd · · Score: 4, Insightful

      How many programs on your system do you *fully* understand? How certain are you about that?

    4. Re:the bug is not in ldd by camperdave · · Score: 2, Funny

      That's why I cross-compile my Gentoo on my Atari 600XL. It may take a few months longer, but it's worth it.

      --
      When our name is on the back of your car, we're behind you all the way!
    5. Re:the bug is not in ldd by bsDaemon · · Score: 5, Funny

      I pretty much only code in Perl these days, so... not even the ones I've written myself, I guess.

    6. Re:the bug is not in ldd by marcansoft · · Score: 4, 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.

  4. Another WIN in WINdows by MyLongNickName · · 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!

    --
    See my journal for slashdot ID's by year. Mine created in 2005. http://slashdot.org/journal/289875/slashdot-ids-by-year
    1. Re:Another WIN in WINdows by Fizzl · · Score: 4, Informative
    2. Re:Another WIN in WINdows by Anonymous Coward · · 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".

    3. Re:Another WIN in WINdows by MyLongNickName · · Score: 4, Informative

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

      --
      See my journal for slashdot ID's by year. Mine created in 2005. http://slashdot.org/journal/289875/slashdot-ids-by-year
    4. Re:Another WIN in WINdows by joebp · · Score: 4, Informative

      depends.exe does exactly this and ships with the platform sdk.

    5. Re:Another WIN in WINdows by onefriedrice · · Score: 3, Insightful

      Also note that Dependency Walker itself might as well be arbitrary code since I can't read its source code.

      --
      This author takes full ownership and responsibility for the unpopular opinions outlined above.
    6. Re:Another WIN in WINdows by Tetsujin · · Score: 4, 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?

      --
      Bow-ties are cool.
    7. Re:Another WIN in WINdows by robogymnast · · 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.

      --
      unzip ; strip ; touch ; grep ; find ; finger ; mount ; fsck ; more ; yes ; fsck ; umount ; sleep
  5. Thorough research by Mortice · · 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'?

    My thorough (3 minute research) turned up this tidbit from TLDP:

    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.

    1. Re:Thorough research by pkrumins · · Score: 2

      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.

    2. Re:Thorough research by marcansoft · · Score: 4, Interesting

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

    3. Re:Thorough research by pkrumins · · Score: 3, Insightful

      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.

    4. Re:Thorough research by Omnifarious · · Score: 2, 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.

    5. Re:Thorough research by Random+Walk · · Score: 2, Informative

      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.

  6. User can choose to run arbitrary code... by alexhs · · 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.

    --
    I have discovered a truly marvelous proof of killer sig, which this margin is too narrow to contain.
    1. Re:User can choose to run arbitrary code... by AndrewNeo · · Score: 3, 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.

  7. Cool and so what by nweaver · · Score: 3, 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

    --
    Test your net with Netalyzr
    1. Re:Cool and so what by Lord+Bitman · · Score: 3, 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

      --
      -- 'The' Lord and Master Bitman On High, Master Of All
    2. Re:Cool and so what by the+99th+penguin · · Score: 4, 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?

    3. Re:Cool and so what by Nevyn · · Score: 2, Interesting

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

      --
      ustr: Managed string API with ave. 44% overhead over strdup(), for 0-20B
    4. Re:Cool and so what by sydneyfong · · Score: 2, 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 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.

      --
      Don't quote me on this.
  8. And the point is... by FlyingBishop · · 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 different ways you can trick him into running arbitrary code, not the least of which is "hey, can you install this for me? I need it to get x done." If you're intelligent enough to hack a binary, I think you're intelligent enough that you can come up with a plausible reason your admin should install something you compiled yourself.

    1. Re:And the point is... by Anonymous Coward · · 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."

  9. Nasty by FranTaylor · · Score: 4, 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.

  10. Don't worry... by wandazulu · · Score: 2, Funny

    ...I'm sure someone will find some other vulnerability.

  11. Specific to Linux? by alcourt · · Score: 4, 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.

    --
    "I may disagree with what you say, but I will defend unto the death your right to say it." -- Voltaire
    1. Re:Specific to Linux? by __aasqbs9791 · · Score: 2, 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.

    2. Re:Specific to Linux? by theCoder · · Score: 2, 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.

      --
      "Save the whales, feed the hungry, free the mallocs" -- author unknown
    3. Re:Specific to Linux? by TorKlingberg · · Score: 2, 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.

    4. Re:Specific to Linux? by Anonymous Coward · · 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.

  12. The bug is not in the dynamic loader by Skapare · · 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).

    --
    now we need to go OSS in diesel cars
  13. New Lingo by Thunderstruck · · Score: 4, 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!"

    --
    Trying to use sarcasm in text-based forums does not work.
  14. Remember to Exit Stage Left by HaloZero · · 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!

    --
    Informatus Technologicus
  15. Other dirty tricks by sjames · · Score: 4, 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.

  16. Rename it! by mweather · · Score: 3, Funny

    They should rename it iddqd in honour of this new feature.

  17. So what? by ledow · · Score: 2, 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.

  18. Documented in ldd(1) and Program Library HOWTO by dwheeler · · Score: 3, Informative

    This is documented, and in multiple places. My Program Library HOWTO, section "Shared Libraries", 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.

    --
    - David A. Wheeler (see my Secure Programming HOWTO)
  19. ldd stuff by Tetsujin · · Score: 2, 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.

    --
    Bow-ties are cool.
  20. Re:The problem is the executable by david_thornley · · Score: 2, 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.

    --
    "When you have eliminated the unacceptable, whatever is left, however improbable, must be the truthiness" - Holmes
  21. Not running as root doesn't mean it's safe by TheLink · · Score: 2, Insightful

    > so I don't wind up running things that don't (like ldd) as root."

    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 getting root means I'm safe" is WRONG!

    As long as we are using the current primitive privilege systems, it's not safe. Windows does allow some sandboxing, but there's a lot of room for improvement. Desktop Linux? There's SELinux and AppArmor, you're welcome to figure out how to make either/both "desktop ready".

    --