block NAT64 local-use prefix in SSRF protection

This commit is contained in:
Athou
2026-11-02 13:09:31 +01:00
parent ddff408afe
commit 01ac8d6ebd
2 changed files with 18 additions and 1 deletions

View File

@@ -56,6 +56,8 @@ public class HttpClientFactory {
private static final DnsResolver DNS_RESOLVER = SystemDefaultDnsResolver.INSTANCE; private static final DnsResolver DNS_RESOLVER = SystemDefaultDnsResolver.INSTANCE;
private static final IPAddress CGNAT_RANGE = new IPAddressString("100.64.0.0/10").getAddress(); private static final IPAddress CGNAT_RANGE = new IPAddressString("100.64.0.0/10").getAddress();
private static final IPAddress NAT64_LOCAL_USE_RANGE =
new IPAddressString("64:ff9b:1::/48").getAddress();
private final CommaFeedConfiguration config; private final CommaFeedConfiguration config;
private final CommaFeedVersion version; private final CommaFeedVersion version;
@@ -149,7 +151,11 @@ public class HttpClientFactory {
} }
private static boolean isLocalAddress(IPAddress ip) { private static boolean isLocalAddress(IPAddress ip) {
if (ip.isLocal() || ip.isLoopback() || ip.isMulticast() || CGNAT_RANGE.contains(ip)) { if (ip.isLocal()
|| ip.isLoopback()
|| ip.isMulticast()
|| CGNAT_RANGE.contains(ip)
|| NAT64_LOCAL_USE_RANGE.contains(ip)) {
return true; return true;
} }

View File

@@ -561,6 +561,17 @@ class HttpGetterTest {
() -> getter.get("http://[64:ff9b::a00:1]")); // 10.0.0.1 () -> getter.get("http://[64:ff9b::a00:1]")); // 10.0.0.1
} }
@Test
void nat64LocalUse() {
// 64:ff9b:1::/48 is reserved for local use (RFC 8215), the whole range is blocked
Assertions.assertThrows(
UnknownHostException.class,
() -> getter.get("http://[64:ff9b:1::a9fe:a9fe]")); // 169.254.169.254
Assertions.assertThrows(
UnknownHostException.class,
() -> getter.get("http://[64:ff9b:1:ffff::a00:1]")); // 10.0.0.1
}
@Test @Test
void sixToFour() { void sixToFour() {
// 2002::/16 embeds the IPv4 address in bits 16-47 (RFC 3056) // 2002::/16 embeds the IPv4 address in bits 16-47 (RFC 3056)