diff --git a/server/src/main/java/cn/keking/web/filter/TrustHostFilter.java b/server/src/main/java/cn/keking/web/filter/TrustHostFilter.java index ca27344a..bc44abfb 100644 --- a/server/src/main/java/cn/keking/web/filter/TrustHostFilter.java +++ b/server/src/main/java/cn/keking/web/filter/TrustHostFilter.java @@ -49,7 +49,10 @@ public class TrustHostFilter implements Filter { String url = WebUtils.getSourceUrl(request); String host = WebUtils.getHost(url); if (isNotTrustHost(host)) { - String html = this.notTrustHostHtmlView.replace("${current_host}", host == null ? "UNKNOWN" : host); + String currentHost = host == null ? "UNKNOWN" : host; + String html = this.notTrustHostHtmlView == null + ? "当前预览文件来自不受信任的站点:" + currentHost + "" + : this.notTrustHostHtmlView.replace("${current_host}", currentHost); response.getWriter().write(html); response.getWriter().close(); } else { @@ -141,15 +144,15 @@ public class TrustHostFilter implements Filter { if (parts.length != 2) { return false; } - int hostInt = parseLiteralIpv4(host); - int networkInt = parseLiteralIpv4(parts[0]); + Long hostInt = parseLiteralIpv4(host); + Long networkInt = parseLiteralIpv4(parts[0]); int prefixLength = Integer.parseInt(parts[1]); - if (hostInt < 0 || networkInt < 0 || prefixLength < 0 || prefixLength > 32) { + if (hostInt == null || networkInt == null || prefixLength < 0 || prefixLength > 32) { return false; } - int mask = prefixLength == 0 ? 0 : -1 << (32 - prefixLength); + long mask = prefixLength == 0 ? 0L : (0xFFFFFFFFL << (32 - prefixLength)) & 0xFFFFFFFFL; return (hostInt & mask) == (networkInt & mask); } catch (NumberFormatException e) { return false; @@ -159,27 +162,27 @@ public class TrustHostFilter implements Filter { /** * 仅解析字面量 IPv4 地址(不做 DNS 解析),防止 DNS rebinding/TOCTOU 风险。 */ - private int parseLiteralIpv4(String input) { + private Long parseLiteralIpv4(String input) { if (input == null || input.trim().isEmpty()) { - return -1; + return null; } String[] parts = input.trim().split("\\."); if (parts.length != 4) { - return -1; + return null; } - int result = 0; + long result = 0L; for (String part : parts) { if (part.isEmpty() || part.length() > 3) { - return -1; + return null; } int value; try { value = Integer.parseInt(part); } catch (NumberFormatException e) { - return -1; + return null; } if (value < 0 || value > 255) { - return -1; + return null; } result = (result << 8) | value; } diff --git a/server/src/test/java/cn/keking/web/filter/TrustHostFilterTests.java b/server/src/test/java/cn/keking/web/filter/TrustHostFilterTests.java index 30eed014..7820cbb6 100644 --- a/server/src/test/java/cn/keking/web/filter/TrustHostFilterTests.java +++ b/server/src/test/java/cn/keking/web/filter/TrustHostFilterTests.java @@ -34,6 +34,15 @@ public class TrustHostFilterTests { assert !trustHostFilter.isNotTrustHost("localhost"); } + @Test + void shouldSupportHighBitIpv4InCidrMatching() { + ConfigConstants.setTrustHostValue("*"); + ConfigConstants.setNotTrustHostValue("200.0.0.0/8"); + + assert trustHostFilter.isNotTrustHost("200.1.2.3"); + assert !trustHostFilter.isNotTrustHost("199.1.2.3"); + } + @Test void shouldDenyWhenHostIsBlankOrNull() { ConfigConstants.setTrustHostValue("*");