From 2e9c99803ba9f1d5284148e83fca0e32c48f01d8 Mon Sep 17 00:00:00 2001 From: Craig Andrews Date: Wed, 3 Jun 2020 14:11:55 -0400 Subject: [PATCH] Reject the NULL character in paths in StrictHttpFirewall Adds `setAllowNull` By default, denies null in paths --- .../web/firewall/StrictHttpFirewall.java | 27 ++++++++++++++++++- .../web/firewall/StrictHttpFirewallTests.java | 14 +++++++++- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/web/src/main/java/org/springframework/security/web/firewall/StrictHttpFirewall.java b/web/src/main/java/org/springframework/security/web/firewall/StrictHttpFirewall.java index c26b27daf6c..8375846aeb7 100644 --- a/web/src/main/java/org/springframework/security/web/firewall/StrictHttpFirewall.java +++ b/web/src/main/java/org/springframework/security/web/firewall/StrictHttpFirewall.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -64,6 +64,9 @@ * Rejects URLs that contain a backslash. See {@link #setAllowBackSlash(boolean)} * *
  • + * Rejects URLs that contain a null character. See {@link #setAllowNull(boolean)} + *
  • + *
  • * Rejects URLs that contain a URL encoded percent. See * {@link #setAllowUrlEncodedPercent(boolean)} *
  • @@ -98,6 +101,8 @@ public class StrictHttpFirewall implements HttpFirewall { private static final List FORBIDDEN_BACKSLASH = Collections.unmodifiableList(Arrays.asList("\\", "%5c", "%5C")); + private static final List FORBIDDEN_NULL = Collections.unmodifiableList(Arrays.asList("\0", "%00")); + private Set encodedUrlBlocklist = new HashSet<>(); private Set decodedUrlBlocklist = new HashSet<>(); @@ -111,6 +116,7 @@ public StrictHttpFirewall() { urlBlocklistsAddAll(FORBIDDEN_FORWARDSLASH); urlBlocklistsAddAll(FORBIDDEN_DOUBLE_FORWARDSLASH); urlBlocklistsAddAll(FORBIDDEN_BACKSLASH); + urlBlocklistsAddAll(FORBIDDEN_NULL); this.encodedUrlBlocklist.add(ENCODED_PERCENT); this.encodedUrlBlocklist.addAll(FORBIDDEN_ENCODED_PERIOD); @@ -281,6 +287,25 @@ public void setAllowBackSlash(boolean allowBackSlash) { } } + /** + *

    + * Determines if a null "\0" or a URL encoded nul "%00" should be allowed in + * the path or not. The default is not to allow this behavior because it is a frequent + * source of security exploits. + *

    + * + * @param allowNull a null "\0" or a URL encoded null "%00" be allowed + * in the path or not. Default is false + * @since 5.4 + */ + public void setAllowNull(boolean allowNull) { + if (allowNull) { + urlBlocklistsRemoveAll(FORBIDDEN_NULL); + } else { + urlBlocklistsAddAll(FORBIDDEN_NULL); + } + } + /** *

    * Determines if a percent "%" that is URL encoded "%25" should be allowed in the path diff --git a/web/src/test/java/org/springframework/security/web/firewall/StrictHttpFirewallTests.java b/web/src/test/java/org/springframework/security/web/firewall/StrictHttpFirewallTests.java index 3de4acc59ea..89971b8355b 100644 --- a/web/src/test/java/org/springframework/security/web/firewall/StrictHttpFirewallTests.java +++ b/web/src/test/java/org/springframework/security/web/firewall/StrictHttpFirewallTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -377,6 +377,18 @@ public void getFirewalledRequestWhenExceedsUpperboundAsciiThenException() { this.firewall.getFirewalledRequest(this.request); } + @Test(expected = RequestRejectedException.class) + public void getFirewalledRequestWhenContainsNullThenException() { + this.request.setRequestURI("/\0"); + this.firewall.getFirewalledRequest(this.request); + } + + @Test(expected = RequestRejectedException.class) + public void getFirewalledRequestWhenContainsEncodedNullThenException() { + this.request.setRequestURI("/something%00/"); + this.firewall.getFirewalledRequest(this.request); + } + // --- from DefaultHttpFirewallTests --- /**