Domain lookup: harden core whois/RDAP (referral SSRF, resolver isolation, structured errors) #2

Open
opened 2026-07-16 00:51:51 +00:00 by James · 0 comments
Owner

Follow-up from the Codex review of api/v2/domains_lookup.php (the app's domain auto-fill). The endpoint wraps core getDomainRecords() in functions.php, which the web UI already exercises, so these are inherited-from-core, not new to the API. The endpoint itself was hardened (IP-literal rejection, per-token throttle, normalisation).

Remaining, in core functions.php:

  1. RDAP redirect / WHOIS referral SSRF (major). RDAP HTTP redirects and whois port-43 referrals are followed without validating the resolved destination IP — a malicious/compromised RDAP service or registrar referral could steer traffic to loopback/private/link-local/metadata addresses. CURLPROTO_HTTPS restricts the scheme, not the destination. Fix: follow redirects manually and validate every hop's resolved IP against a deny-list of internal ranges; resolve+validate whois referral hosts before connecting. (Responses aren't dereferenced, so no data-exfil SSRF — but connections still occur.) An egress firewall is the pragmatic defence-in-depth.
  2. Split-horizon / internal-resolver oracle (major). Lookups use the system resolver, so internal split-horizon A/NS/MX are visible. Prefer an isolated public resolver and Public-Suffix-List validation of registrable domains.
  3. Structured upstream errors (minor). NXDOMAIN, DNS failure, RDAP/whois timeout all collapse to empty records → the app shows "no records found" even on transient infra failure. Have getDomainRecords() distinguish authoritative no-data from upstream failure; surface 502/504.
  4. Remove the unused TXT lookup (functions.php:1372) — fetched but never used.

Scope note: proper fixes need a PSL library + isolated resolver + manual redirect validation in core; deferred to keep fork↔core divergence minimal (the web UI has the same exposure today).

Follow-up from the Codex review of `api/v2/domains_lookup.php` (the app's domain auto-fill). The endpoint wraps core `getDomainRecords()` in `functions.php`, which the **web UI already exercises**, so these are inherited-from-core, not new to the API. The endpoint itself was hardened (IP-literal rejection, per-token throttle, normalisation). Remaining, in core `functions.php`: 1. **RDAP redirect / WHOIS referral SSRF (major).** RDAP HTTP redirects and whois port-43 referrals are followed without validating the resolved destination IP — a malicious/compromised RDAP service or registrar referral could steer traffic to loopback/private/link-local/metadata addresses. `CURLPROTO_HTTPS` restricts the scheme, not the destination. Fix: follow redirects manually and validate every hop's resolved IP against a deny-list of internal ranges; resolve+validate whois referral hosts before connecting. (Responses aren't dereferenced, so no data-exfil SSRF — but connections still occur.) An egress firewall is the pragmatic defence-in-depth. 2. **Split-horizon / internal-resolver oracle (major).** Lookups use the system resolver, so internal split-horizon A/NS/MX are visible. Prefer an isolated public resolver and Public-Suffix-List validation of registrable domains. 3. **Structured upstream errors (minor).** NXDOMAIN, DNS failure, RDAP/whois timeout all collapse to empty records → the app shows "no records found" even on transient infra failure. Have `getDomainRecords()` distinguish authoritative no-data from upstream failure; surface 502/504. 4. **Remove the unused TXT lookup** (`functions.php:1372`) — fetched but never used. Scope note: proper fixes need a PSL library + isolated resolver + manual redirect validation in core; deferred to keep fork↔core divergence minimal (the web UI has the same exposure today).
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
James/itflow#2
No description provided.