From 2ee2de87f1da7c04c58c8057016893b1ec2cc347 Mon Sep 17 00:00:00 2001 From: a3vX Date: Sat, 16 Aug 2025 11:25:56 +0200 Subject: [PATCH 1/2] Add: new testbed for XWiki_CVE_2025_24893 --- xwiki/CVE-2025-24893/Dockerfile | 66 ++++++++++++ xwiki/CVE-2025-24893/README.md | 22 ++++ xwiki/CVE-2025-24893/xwiki-init.py | 155 +++++++++++++++++++++++++++++ 3 files changed, 243 insertions(+) create mode 100644 xwiki/CVE-2025-24893/Dockerfile create mode 100644 xwiki/CVE-2025-24893/README.md create mode 100644 xwiki/CVE-2025-24893/xwiki-init.py diff --git a/xwiki/CVE-2025-24893/Dockerfile b/xwiki/CVE-2025-24893/Dockerfile new file mode 100644 index 00000000..a6fcb55f --- /dev/null +++ b/xwiki/CVE-2025-24893/Dockerfile @@ -0,0 +1,66 @@ +# Arguments +ARG JAVA_VERSION=17 +ARG XWIKI_VERSION=17.4.3 +# Change at build time to 15.10.10 for a vulnerable version + +FROM openjdk:${JAVA_VERSION}-jdk-slim + +ARG XWIKI_VERSION +ENV XWIKI_DOWNLOAD_URL=https://nexus.xwiki.org/nexus/content/repositories/releases/org/xwiki/platform/xwiki-platform-distribution-jetty-hsqldb/${XWIKI_VERSION}/xwiki-platform-distribution-jetty-hsqldb-${XWIKI_VERSION}.zip + +# Creating non-root user for XWiki +RUN useradd -ms /bin/bash xwiki + +# Update and install required packages +RUN apt-get update && \ + apt-get install -y wget unzip ca-certificates python3-requests && \ + rm -rf /var/lib/apt/lists/* + +WORKDIR /opt +ENV DIR_XWIKI=/opt/xwiki + +# Downloading XWiki +RUN wget --quiet --show-progress --tries=3 -O xwiki.zip "${XWIKI_DOWNLOAD_URL}" && \ + unzip xwiki.zip && \ + rm xwiki.zip && \ + mv xwiki-platform-distribution-jetty-hsqldb-${XWIKI_VERSION} xwiki && \ + chown -R xwiki:xwiki ${DIR_XWIKI} + +# Exposing port 8080 for Jetty +EXPOSE 8080 + +# Upload init scripts +ENV SCRIPT_INIT=xwiki-init.py +COPY ${SCRIPT_INIT} ${DIR_XWIKI} +RUN chmod +x ${DIR_XWIKI}/${SCRIPT_INIT} && \ + chown xwiki:xwiki ${DIR_XWIKI}/${SCRIPT_INIT} + +# permanentDirectory +# ENV DIR_PERMANENT=/var/lib/xwiki/data +ENV DIR_PERMANENT=${DIR_XWIKI}/data +# RUN mkdir -p ${DIR_PERMANENT} && \ +# chown -R xwiki:xwiki ${DIR_PERMANENT} + +# If needed to persist data +# VOLUME ["${DIR_PERMANENT}"] + +# Using xwiki user now +USER xwiki + +# Offline Repository for installing Standard Flavor +ENV DIR_REPOSITORY=${DIR_PERMANENT}/extension/repository +RUN mkdir -p ${DIR_REPOSITORY} +WORKDIR ${DIR_REPOSITORY} + +RUN wget --quiet --show-progress --tries=3 -O repository.zip https://nexus.xwiki.org/nexus/content/groups/public/org/xwiki/platform/xwiki-platform-distribution-flavor-xip/${XWIKI_VERSION}/xwiki-platform-distribution-flavor-xip-${XWIKI_VERSION}.xip && \ + unzip repository.zip && \ + rm repository.zip + + +WORKDIR ${DIR_XWIKI} + +# Starting Jetty + XWiki +# CMD ["./start_xwiki.sh"] + +# Automating the installation process +CMD ["/bin/bash", "-c", "/usr/bin/python3 ${DIR_XWIKI}/${SCRIPT_INIT}"] diff --git a/xwiki/CVE-2025-24893/README.md b/xwiki/CVE-2025-24893/README.md new file mode 100644 index 00000000..bc8024c4 --- /dev/null +++ b/xwiki/CVE-2025-24893/README.md @@ -0,0 +1,22 @@ + +To build and start a vulnerable XWiki instance: +```sh +docker build --build-arg XWIKI_VERSION=15.10.10 --build-arg JAVA_VERSION=11 -t xwiki:15.10.10 . +docker run -d -p 8080:8080 --name xwiki -it xwiki:15.10.10 +``` + +To build and start a patched XWiki instance: +```sh +docker build --build-arg XWIKI_VERSION=17.4.3 -t xwiki:17.4.3 . +docker run -d -p 8080:8080 --name xwiki -it xwiki:17.4.3 +``` + +By default, the script xwiki-init.py is executed (see end of Dockerfile) and automates the following installation steps : +- Wait that XWiki / Jetty starts +- Connect to http://:8080/xwiki +- Click on "Continue" +- Fulfill the form to create the admin account, then click on "Continue" after the success message is displayed +- Select the Flavor "XWiki Standard Flavor". The page may need to be reloaded if it does not display directly +- Click on "Continue" to continue with the installation process +- When XWiki is successfully set up, you will be redirected from `/bin/distribution/XWiki/Distribution` to `/bin/view/Main/` + diff --git a/xwiki/CVE-2025-24893/xwiki-init.py b/xwiki/CVE-2025-24893/xwiki-init.py new file mode 100644 index 00000000..edab314a --- /dev/null +++ b/xwiki/CVE-2025-24893/xwiki-init.py @@ -0,0 +1,155 @@ +#!/usr/bin/python3 + +import datetime +import random, re, requests +import sys, string, subprocess +import time + + + +# First, launch XWiki +proc_xwiki = subprocess.Popen(['/opt/xwiki/start_xwiki.sh']) +time.sleep(5) + + +# Defining variables and functions +baseUrl = 'http://127.0.0.1:8080/xwiki' +distributionUrl = '%s/bin/distribution/XWiki/Distribution' %baseUrl + +def printLog(msg): + dateStr = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S,%f")[:-3] + print('%s [%s] %s' %(dateStr, 'XWiki-Init', msg)) + +def dieOnError(msg): + printLog('An error occurred while installing XWiki: %s' %msg) + #sys.exit(1) + +def check_xwiki_ok(): + rep = rs.get(distributionUrl, allow_redirects=False) + return rep.status_code == 302 and 'Location' in rep.headers and '/bin/view/Main/' in rep.headers['Location'] + +def check_solrsearch_ok(): + solrSearchEndUrl = '/bin/view/Main/SolrSearch' + rep = rs.get(baseUrl+solrSearchEndUrl, allow_redirects=False) + return rep.status_code == 302 and 'Location' in rep.headers and solrSearchEndUrl in rep.headers['Location'] + +def processInstall(): + if check_xwiki_ok(): + printLog('XWiki already set up') + else: + # Waiting XWiki to be ready + rep = rs.get(distributionUrl) + while '

Distribution Wizard

' not in rep.text: + time.sleep(5) + rep = rs.get(distributionUrl) + printLog('XWiki started') + + # Click on the "Continue" button + rep = rs.get(distributionUrl+'?action=COMPLETE_STEP') + if '

Step 1 - Admin user

' not in rep.text: + return dieOnError('expecting admin step') + + # Creating an administrator account + admUser = 'admin' + admPasswd = ''.join(random.choices(string.ascii_letters + string.digits, k=30)) + printLog('Creating administrator account... [%s:%s]' %(admUser,admPasswd)) + + rep = rs.post(distributionUrl, data = { + 'register_first_name': 'test', + 'register_last_name': 'test', + 'xwikiname': admUser, + 'register_password': admPasswd, + 'register2_password': admPasswd, + 'register_email': 'test@test.fr', + }) + + # Admin account created + if 'You are connected with user' not in rep.text: + return dieOnError('expecting admin created') + + # Click on the "Continue" button + rep = rs.get(distributionUrl+'?action=COMPLETE_STEP') + if '

Step 2 - Flavor

' not in rep.text: + return dieOnError('expecting flavor step') + + # Chosing XWiki Standard Flavor + printLog('Searching for XWiki Standard Flavor...') + i = 0 + iMax = 5 + while i < iMax: + rep = rs.get(baseUrl+'/bin/get/resources/uicomponents/flavor?xpage=flavor/picker_flavors&namespace=wiki:xwiki') + rjs = rep.json() + if len(rjs)<1 or 'id' not in rjs[0] or 'id' not in rjs[0]['id'] or 'version' not in rjs[0]['id'] or 'value' not in rjs[0]['id']['version'] or 'name' not in rjs[0] or rjs[0]['name']!='XWiki Standard Flavor': + time.sleep(5) + i += 1 + continue + break + if i == iMax: + return dieOnError('standard flavor not found') + + printLog('Installing Flavor. This may take a while') + + installFlavorData = { + 'installFlavor': 'Install this flavor', + 'fieldName': 'flavor', + 'flavor': '%s:::%s' %(rjs[0]['id']['id'], rjs[0]['id']['version']['value']), + } + rep = rs.post(distributionUrl, data = installFlavorData) + + if '