Skip to content
This repository was archived by the owner on May 29, 2026. It is now read-only.

fix: GisProxyService SSRF — allowlist bypass + getCapabilities pre-auth missing (C5)#662

Merged
rubenvdlinde merged 1 commit into
developmentfrom
fix/critical-gis-ssrf
May 27, 2026
Merged

fix: GisProxyService SSRF — allowlist bypass + getCapabilities pre-auth missing (C5)#662
rubenvdlinde merged 1 commit into
developmentfrom
fix/critical-gis-ssrf

Conversation

@rubenvdlinde

Copy link
Copy Markdown
Contributor

Summary

Fixes the two SSRF vulnerabilities in GisProxyService (issue C5).

C5 — getCapabilities bypasses allowlist entirely:
getCapabilities called file_get_contents($capUrl) without first calling isUrlAllowed. Any URL could be passed — including file:///etc/passwd and php://filter/... — and would be fetched and returned in the response body. The method now calls isUrlAllowed at the top and throws 403 if not allowed.

C5 — Substring allowlist bypass:
isUrlAllowed used str_contains($url, 'pdok.nl') which is bypassable via https://evil.com/?x=pdok.nl. Replaced with:

  • A TRUSTED_HOSTNAMES list of exact PDOK/Kadaster host names (checked by exact $host === $trusted comparison)
  • parse_url() to extract the hostname for comparison — no string-scanning of the full URL
  • Scheme allowlist: only https permitted; file://, php://, data: etc. blocked at entry

C5 — SSRF against internal services:
Added isHostSafeFromSsrf() which resolves the hostname via gethostbyname() and checks the resulting IP against RFC1918 (10/8, 172.16/12, 192.168/16), loopback (127/8), and link-local (169.254/16) CIDR ranges.

Test plan

  • 9 PHPUnit tests pass (5 existing + 4 new)
  • testGetCapabilitiesBlocksDisallowedUrl — 403 on non-allowlisted URL
  • testNonHttpsSchemeIsBlocked — 403 on file:// URL
  • testSubstringBypassUrlIsBlockedhttps://evil.com/?x=pdok.nl rejected (was allowed before fix)
  • testPhpStreamWrapperIsBlockedphp://filter/... rejected

Closes #638

…t check (C5)

- C5: getCapabilities now calls isUrlAllowed() before file_get_contents — previously
  it bypassed the allowlist entirely, allowing file:// LFI and php:// wrappers
- C5: isUrlAllowed rewritten to use exact hostname comparison (not str_contains
  substring) — prevents https://evil.com/?x=pdok.nl bypass
- C5: Add scheme allowlist — only https permitted; file://, php://, data: etc. blocked
- C5: Add SSRF CIDR block — resolves hostname to IP and blocks RFC1918 (10/8, 172.16/12,
  192.168/16), loopback (127/8), and link-local (169.254/16)
- C5: TRUSTED_HOSTNAMES list replaces the substring pdok.nl/kadaster.nl checks
- 4 new security tests: getCapabilities blocked, non-https blocked, substring-bypass
  blocked, php:// stream wrapper blocked
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant