Publish Constants for Firewall Header and Parameter Predicates

Introduced public static final Predicates for allowed header names,
header values, parameter names, and parameter values for building
expressions.

Closes gh-13639
This commit is contained in:
baezzys 2024-06-01 12:15:44 +09:00 committed by Josh Cummings
parent df76537470
commit 4169c0cf36
2 changed files with 51 additions and 4 deletions

View File

@ -75,6 +75,7 @@ import org.springframework.util.Assert;
*
* @author Rob Winch
* @author Eddú Meléndez
* @author Jinwoo Bae
* @since 4.2.4
* @see DefaultHttpFirewall
*/
@ -134,13 +135,21 @@ public class StrictHttpFirewall implements HttpFirewall {
private static final Predicate<String> HEADER_VALUE_PREDICATE = (s) -> HEADER_VALUE_PATTERN.matcher(s).matches();
private Predicate<String> allowedHeaderNames = ASSIGNED_AND_NOT_ISO_CONTROL_PREDICATE;
private Predicate<String> allowedHeaderNames = ALLOWED_HEADER_NAMES;
private Predicate<String> allowedHeaderValues = HEADER_VALUE_PREDICATE;
public static final Predicate<String> ALLOWED_HEADER_NAMES = ASSIGNED_AND_NOT_ISO_CONTROL_PREDICATE;
private Predicate<String> allowedParameterNames = ASSIGNED_AND_NOT_ISO_CONTROL_PREDICATE;
private Predicate<String> allowedHeaderValues = ALLOWED_HEADER_VALUES;
private Predicate<String> allowedParameterValues = (value) -> true;
public static final Predicate<String> ALLOWED_HEADER_VALUES = HEADER_VALUE_PREDICATE;
private Predicate<String> allowedParameterNames = ALLOWED_PARAMETER_NAMES;
public static final Predicate<String> ALLOWED_PARAMETER_NAMES = ASSIGNED_AND_NOT_ISO_CONTROL_PREDICATE;
private Predicate<String> allowedParameterValues = ALLOWED_PARAMETER_VALUES;
public static final Predicate<String> ALLOWED_PARAMETER_VALUES = (value) -> true;
public StrictHttpFirewall() {
urlBlocklistsAddAll(FORBIDDEN_SEMICOLON);

View File

@ -31,6 +31,7 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
/**
* @author Rob Winch
* @author Eddú Meléndez
* @author Jinwoo Bae
*/
public class StrictHttpFirewallTests {
@ -723,6 +724,14 @@ public class StrictHttpFirewallTests {
assertThatExceptionOfType(RequestRejectedException.class).isThrownBy(() -> request.getHeader("bad name"));
}
@Test
public void getFirewalledRequestWhenHeaderNameNotAllowedWithAugmentedHeaderNamesThenException() {
this.firewall
.setAllowedHeaderNames(StrictHttpFirewall.ALLOWED_HEADER_NAMES.and((name) -> !name.equals("bad name")));
HttpServletRequest request = this.firewall.getFirewalledRequest(this.request);
assertThatExceptionOfType(RequestRejectedException.class).isThrownBy(() -> request.getHeader("bad name"));
}
@Test
public void getFirewalledRequestGetHeaderWhenNotAllowedHeaderValueThenException() {
this.request.addHeader("good name", "bad value");
@ -731,6 +740,15 @@ public class StrictHttpFirewallTests {
assertThatExceptionOfType(RequestRejectedException.class).isThrownBy(() -> request.getHeader("good name"));
}
@Test
public void getFirewalledRequestWhenHeaderValueNotAllowedWithAugmentedHeaderValuesThenException() {
this.request.addHeader("good name", "bad value");
this.firewall.setAllowedHeaderValues(
StrictHttpFirewall.ALLOWED_HEADER_VALUES.and((value) -> !value.equals("bad value")));
HttpServletRequest request = this.firewall.getFirewalledRequest(this.request);
assertThatExceptionOfType(RequestRejectedException.class).isThrownBy(() -> request.getHeader("good name"));
}
@Test
public void getFirewalledRequestGetDateHeaderWhenControlCharacterInHeaderNameThenException() {
this.request.addHeader("Bad\0Name", "some value");
@ -840,6 +858,16 @@ public class StrictHttpFirewallTests {
.isThrownBy(() -> request.getParameterValues("Something"));
}
@Test
public void getFirewalledRequestWhenParameterValueNotAllowedWithAugmentedParameterValuesThenException() {
this.request.addParameter("Something", "bad value");
this.firewall.setAllowedParameterValues(
StrictHttpFirewall.ALLOWED_PARAMETER_VALUES.and((value) -> !value.equals("bad value")));
HttpServletRequest request = this.firewall.getFirewalledRequest(this.request);
assertThatExceptionOfType(RequestRejectedException.class)
.isThrownBy(() -> request.getParameterValues("Something"));
}
@Test
public void getFirewalledRequestGetParameterValuesWhenNotAllowedInParameterNameThenException() {
this.firewall.setAllowedParameterNames((value) -> !value.equals("bad name"));
@ -849,6 +877,16 @@ public class StrictHttpFirewallTests {
.isThrownBy(() -> request.getParameterValues("bad name"));
}
@Test
public void getFirewalledRequestWhenParameterNameNotAllowedWithAugmentedParameterNamesThenException() {
this.request.addParameter("bad name", "good value");
this.firewall.setAllowedParameterNames(
StrictHttpFirewall.ALLOWED_PARAMETER_NAMES.and((value) -> !value.equals("bad name")));
HttpServletRequest request = this.firewall.getFirewalledRequest(this.request);
assertThatExceptionOfType(RequestRejectedException.class)
.isThrownBy(() -> request.getParameterValues("bad name"));
}
// gh-9598
@Test
public void getFirewalledRequestGetParameterWhenNameIsNullThenIllegalArgumentException() {