In an attempt to save the world from disaster, Solar Designer wrote: > Hello, > > There's another problem in ld-linux.so (and the a.out linker ld.so, too): > it is possible to trick the linker into loading old version of a library > if several versions are installed. This means that if you have upgraded > your libc (or libdb, etc) after a security hole was discovered, updated > /etc/ld.so.cache with ldconfig, and made sure the new version is used, > it still might be possible for an attacker to force a setuid binary into > using your old vulnerable version of the library, if you haven't removed > it from the directories scanned by ldconfig. > > The problem is that ldconfig adds all versions of a library into the cache, > and the linker itself doesn't give up if an error occurs. Normally the > latest version is listed first, and it's the only one used. However, we > can consume up the resources, so that the linker fails to load the latest > version, and then free some resources before it tries to load an older one. It's much simpler than that: $ LD_PRELOAD=libdoesntexist /bin/su /bin/su: error in loading shared libraries libdoesntexist: cannot open shared object file: No such file or directory In other words, just use LD_PRELOAD. It is _not_ ignored on setuid binaries. (Something I wrote about the dangers of this some time ago): I linux (and the Solaris) dynamic linkers don't ignore LD_PRELOAD for setuid binaries. The documentation of the old (libc5, aka ld.so 1.8.1, 1.9 etc) said (incorrectly) that LD_PRELOAD was ignored when executing setuid binaries, and this is the behaviour I've always expected. But apparently the wisdom is that libraries that are installed on the system should be well written, and it should be safe for them to be specified in LD_PRELOAD. I am quite surprised by this attitude, and I think I've thought of 3 situations where this behaviour of the dynamic linkers may _possibly_ create security problems. I very much welcome responces from peope on this list. (Like: "Don't worry, you silly newbie, we know what we are doing" or "My god, this is a big concern" or anything in between). (If you don't believe the dynamic linkers ignore LD_PRELOAD on setuid bins, type "LD_PRELOAD=libdoesntexist /bin/su".) ********************** - Buffer overruns in global initialisers (C++). Suppose you've got a 10000+ line C++ library that does linguistic analysis of various languages. Now _somewhere_ in that library, someone on the project added the following code: class foo{ public: foo(){ char buf[10], *s=getenv("FOO"); if(s) strcpy(buf,s); // Buffer overrun, etc. // [more code here] } }; foo bar; // initialise this variable. (before main() is called) Having this library installed in any location in /usr/lib, or /lib (more general: any directory listed in /etc/ld.so.conf) will make your whole system vurnerable for attac. Again one may argue that libraries like this don't belong in /usr/lib. But you argue that way, then basically no big library belongs in /usr/lib. Again, not current practice. ********************** - Wrapper libraries that override important system functions. Because many of these wrapper libraries will be written based on the assumption that their code will not be part of any setuid binary, the wrapping functions are not "defensively programmed", and as such may well be vurnerable to buffer overruns etc. It may be argued that these libraries don't belong in /usr/lib etc, but the fact is that (maybe due to the misleading documentation) they currently often are. ********************** - Surprising results of name-overlaps. As an example, take another artificial-intelligence library that makes attempts at answering simple english questions. One friday afternoon the linguists added the function "crypt(const *char q)" that attempts to not give a straight answer to the question, but a cryptic one. Naturally, this question q is copied to a 80 byte-long array on the stack. Well, you get the idea: type LD_PRELOAD=libAI.so.2.3 /bin/su and su will eventually call crypt(key,salt), with key being the user-typed (max 128 chars, see getpass(3)) password. Should be root in there somewhere. In general: setuid binaries rely on many functions in system libraries. Some of these functions have names that also have meanings in other fields, and as such may be implemented in completely unrelated libraries. Because it is possible to trick the setuid binaries into using any library installed on the system, all these functions can potentially be called by setuid biaries, with 'interesting' effects. I don't want to imply that applies to your system at this moment -- all I want to say is that there _is_ a potential security problem. Thanks, -- joost witteveen, joostjeat_private The upstream maintainer is allowed to do things different than Debian, but only if he has good reasons to do so.
This archive was generated by hypermail 2b30 : Fri Apr 13 2001 - 13:42:06 PDT