View on GitHub
Local educational use only. Never deploy on a public-facing server.

DVLA: Damn Vulnerable Laravel Application for AppSec Training

A modern, guided security lab targeting real-world Laravel stack exploits.
Built for OSWE prep, AppSec training, and Laravel developers who want to understand
what production vulnerabilities actually look like, and how they chain together.

Why DVLA?

DVWA and similar tools demonstrate generic, early-era web vulnerabilities on outdated PHP. DVLA targets the real attack surface of a modern Laravel stack.

LEMP Stack

PHP 8.2, Laravel 12, Livewire 3, Docker Compose, Redis & Horizon. The same stack running in production today, not CGI-era PHP.

Full Kill Chain

Vulnerabilities chain into a complete host compromise: .env leak -> APP_KEY RCE -> Redis job injection -> docker.sock escape.

Blog-Guided

Every exploit module has a companion post right here with source code walkthroughs, proof-of-concept steps, and side-by-side remediation.

The Kill Chain

Five individually defensible shortcuts that compound into a full host compromise.

1
Nginx
.env exposed, readable via HTTP
2
Credentials
APP_KEY extracted from .env
3
Laravel App
Forged cookie -> deserialization RCE
4
Redis
No-auth queue backend -> job injection
5
Docker
docker.sock mounted -> host escape

Vulnerability Modules

Eight intentional misconfigurations across the full stack. Explore each one in your own local instance, then check the companion blog series below for the full walkthrough.

Easy
Mass Assignment

Eloquent model lacks $fillable, so the registration endpoint accepts is_admin=1 and grants admin on signup.

IDOR

Sequential numeric IDs in URLs plus a controller that filters ownership on the list view but not the detail view lets any authenticated user read any object by changing the ID number.

Open Redirect

An unvalidated redirect query parameter lets an attacker craft phishing URLs that appear to originate from the trusted application domain.

Medium
PHP Type Juggling

Custom auth uses == instead of ===, so magic hash values like 0e... bypass authentication entirely.

SQL Injection

User input concatenated into raw SQL via DB::select() on an unauthenticated search endpoint lets SQLMap dump the entire database, user emails, bcrypt hashes, and session tokens, in under two minutes.

Livewire File Upload Bypass

Component trusts MIME type over extension. Upload a .php shell as image/png and it lands in public/storage/ ready to execute.

Stored XSS

User-controlled content injection. Stored XSS is the highest-impact variant: the payload executes automatically for every visitor.

Race Condition

Concurrent requests exploit a time-of-check-to-time-of-use gap in business logic, enabling privilege escalation or duplicate operations that should have been prevented.

Hard
.env Exposure + APP_KEY -> RCE

Nginx misconfiguration serves the .env file over HTTP, exposing APP_KEY, database credentials, and all secrets.

SSRF

The server is tricked into making requests to internal services (Redis, metadata endpoints, internal APIs), bridging from the application layer into the internal network without any external-facing port.

Redis Job Injection

Unauthenticated Redis exposed on all interfaces. Push a serialized Laravel job directly and the Horizon worker picks it up and executes it.

Docker Escape

/var/run/docker.sock mounted into a root-running container lets an attacker with existing RCE spawn a privileged container with the host filesystem bind-mounted, gaining full root access to the host.

SSTI

Server-side template injection in Blade views lets an attacker inject template directives that execute arbitrary PHP on the server, providing yet another RCE primitive.

Companion Blog Series

Full write-ups for every module above. Each post includes source code review, step-by-step exploit, and remediation.

Start Here: Getting DVLA Running Locally

Clone and build the full Docker lab.