CME-1304

SSRF Prevention (Outbound Request Allowlist)

Description

Application-level validation that restricts server-initiated requests to an explicit allowlist of permitted schemes, destinations, ports, and paths. The application canonicalizes the URL once, rejects embedded credentials and ambiguous representations, resolves the destination before connecting, validates every resolved IPv4 and IPv6 address, and uses the validated address for the connection to prevent DNS rebinding and time-of-check/time-of-use bypasses. It rejects loopback, link-local, private, unique-local, multicast, and unspecified address ranges; disables unsupported schemes such as file:// and gopher://; revalidates every redirect target; prevents unintended proxy use; and limits response size and duration. This SSRF-specific control specializes the general allowlist pattern in CME-1315. Network egress restriction in CME-208 provides defense in depth when application validation is bypassed.

CVSS Vector Impacts

Metric Transition Rationale
Confidentiality (C) H L A correctly enforced destination allowlist prevents the application from retrieving high-value data from internal services, cloud metadata endpoints, and local files. Low confidentiality impact remains possible through data exposed by an explicitly permitted destination or through limited information disclosed by rejection and timing behavior. This attenuation applies only when address validation is bound to the connection and repeated for every redirect.

CWE Relationships

Verification

Review the outbound request implementation and dynamically test its application-specific SSRF sink. Confirm explicit allowlist enforcement; single-pass canonicalization; validation of every resolved IPv4 and IPv6 address; connection to the validated address; redirect revalidation; rejection of credentials, unsupported schemes, ambiguous address forms, loopback, link-local, private, unique-local, multicast, and unspecified ranges; proxy restrictions; and response size and timeout limits. The test endpoint must accept the candidate destination through a url query parameter; adapt the request wrapper if the application uses a different interface.

$ test -n "$CME_SSRF_TEST_ENDPOINT" || { echo 'ERROR: set CME_SSRF_TEST_ENDPOINT'; exit 2; }; failed=0; for payload in 'http://169.254.169.254/latest/meta-data/' 'http://127.0.0.1/' 'http://[::1]/' 'http://10.0.0.1/' 'http://172.16.0.1/' 'http://192.168.0.1/' 'http://[fc00::1]/' 'http://[fe80::1]/' 'file:///etc/passwd' 'gopher://127.0.0.1:11211/_stats' 'http://2130706433/' 'http://0177.0.0.1/' 'http://user@127.0.0.1/'; do code=$(curl -sS --max-time 10 -o /dev/null -w '%{http_code}' -G --data-urlencode "url=$payload" "$CME_SSRF_TEST_ENDPOINT") || failed=1; case "$code" in 400|403) ;; *) printf 'FAIL %s -> %s\n' "$payload" "$code"; failed=1 ;; esac; done; test "$failed" -eq 0 && echo 'PASS: all direct SSRF payloads rejected'
# Expected: PASS: all direct SSRF payloads rejected
Platform: any
$ test -n "$CME_SSRF_TEST_ENDPOINT" && test -n "$CME_SSRF_REDIRECT_URL" && code=$(curl -sS --max-time 10 -o /dev/null -w '%{http_code}' -G --data-urlencode "url=$CME_SSRF_REDIRECT_URL" "$CME_SSRF_TEST_ENDPOINT") && case "$code" in 400|403) echo 'PASS: redirect to prohibited destination rejected' ;; *) printf 'FAIL: redirect payload returned %s\n' "$code"; exit 1 ;; esac
# Expected: PASS: redirect to prohibited destination rejected
Platform: any
$ test -n "$CME_SSRF_TEST_ENDPOINT" && test -n "$CME_SSRF_REBIND_URL" && code=$(curl -sS --max-time 10 -o /dev/null -w '%{http_code}' -G --data-urlencode "url=$CME_SSRF_REBIND_URL" "$CME_SSRF_TEST_ENDPOINT") && case "$code" in 400|403) echo 'PASS: DNS rebinding target rejected' ;; *) printf 'FAIL: rebinding payload returned %s\n' "$code"; exit 1 ;; esac
# Expected: PASS: DNS rebinding target rejected
Platform: any
← CME-1303: Application-Level Filesystem Access Confinement CME-1305: SQL Injection Prevention (Parameterized Queries) →