Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

security issue with set-uid and a relative path for INTERP (dynamic linker) in ELF

The combination of set-uid and a relative path in the INTERP section of an ELF binary is very dangerous.

I'm not quite sure how and where this problem should be reported, but it seems to me like a general security issue concerning how dynamic linking in linux/glibc works, so let me explain what it is:

Consider building a dynamically linked binary and specifying a relative path in the ELF INTERP section (using the --dynamic-linker gcc option) so you could redistribute a custom glibc version with your dynamically linked commercial application (where you are not allowed to link statically against the LGPL glibc, but still need to make your binary work across different linux distribution having different glibc versions).

If you chown the binary to root, and put the set-uid flag on your binary, it effectively becomes a rootkit. As executing it from a different directory, allows you to replace the dynamic linker executable, that will be executed with root permission.

To demonstrate this, take a look at the following C code (issue.c):

#include <stdio.h> 

// 
// build with: 
//   gcc -DNAME=\"vulnarable\" -o issue -Wl,--dynamic-linker,.lib64/ld-linux-x86-64.so.2 issue.c 
//   sudo chown root issue 
//   sudo chmod u+s issue 
// now build some code to be executed with root permissions (we use the same issue.c): 
//   mkdir -p .lib64/ 
//   gcc -DNAME=\"rootkit\" -o .lib64/ld-linux-x86-64.so.2 --static issue.c 
// 

int main(int argc, char* argv[]) 
{ 
    printf("(%s) euid:%d\n", NAME, geteuid()); 
} 

If you now execute the set-uid binary like this

./issue

or even just doing this

ldd issue

instead of getting what you might expect, e.g.:

(vulnarable) euid:0

you get:

(rootkit) euid:0

Now the point is you could replace the ld-linux-x86-64.so.6 binary with whatever you like.

Similar issues seems to have been addressed, by not resolving $ORIGIN in RPATH or ignoring LD_LIBRARY_PATH if the set-uid flag is set.

So I wonder if the INTERP in ELF has to be ignored, whenever the set-uid flag is set (i.e. by using the default dynamic linker - /lib32/ld-linux.so.2 or /lib64/ld-linux-x86-64.so.2)?

So what do you think, where should this be fixed or reported - in glibc or the kernel?

like image 448
siddhadev Avatar asked Jan 26 '12 13:01

siddhadev


1 Answers

Yes, it is not safe to have a setuid binary specifying an interpreter in a non-safe location (you mention relative path, but a world-writable fixed path has the same issue). But it's logical conclusion of the ELF design, and adding a special-case to the handling of INTERP for setuid binaries is not the way to go. It's a case of “Doctor, it hurts when I do this. — Don't do it.” Yes, this combination is unsafe, so simply don't use it! Meddling with the ELF interpreter is something rather advanced anyway, so you shouldn't do it unless you understand what you're doing, in which case you can logically conclude what is safe or not to do.

Advanced features of ELF/POSIX/Unix/whatever give you powerful ways to shoot yourself in the foot, because they are powerful. If you wanted to get rid of every possible bad situation, you would have a system much less flexible and much harder to program for, while still having some holes in it.

like image 118
F'x Avatar answered Oct 05 '22 20:10

F'x