Pārlūkot izejas kodu

Add Header and Parameter Value Documentation

Closes gh-9038
Josh Cummings 4 gadi atpakaļ
vecāks
revīzija
a6d19474c4

+ 101 - 0
docs/manual/src/docs/asciidoc/_includes/servlet/exploits/firewall.adoc

@@ -131,3 +131,104 @@ See https://jira.spring.io/browse/SPR-16851[SPR_16851] for an issue requesting t
 
 If you must allow any HTTP method (not recommended), you can use `StrictHttpFirewall.setUnsafeAllowAnyHttpMethod(true)`.
 This will disable validation of the HTTP method entirely.
+
+`StrictHttpFirewall` also checks header names and values and parameter names.
+It requires that each character have a defined code point and not be a control character.
+
+This requirement can be relaxed or adjusted as necessary using the following methods:
+
+* `StrictHttpFirewall#setAllowedHeaderNames(Predicate)`
+* `StrictHttpFirewall#setAllowedHeaderValues(Predicate)`
+* `StrictHttpFirewall#setAllowedParameterNames(Predicate)`
+
+NOTE: Also, parameter values can be controlled with `setAllowedParameterValues(Predicate)`.
+
+For example, to switch off this check, you can wire your `StrictHttpFirewall` with `Predicate` s that always return `true`, like so:
+
+.Allow Any Header Name, Header Value, and Parameter Name
+====
+.Java
+[source,java,role="primary"]
+----
+@Bean
+public StrictHttpFirewall httpFirewall() {
+    StrictHttpFirewall firewall = new StrictHttpFirewall();
+    firewall.setAllowedHeaderNames((header) -> true);
+    firewall.setAllowedHeaderValues((header) -> true);
+    firewall.setAllowedParameterNames((parameter) -> true);
+    return firewall;
+}
+----
+
+.Kotlin
+[source,kotlin,role="secondary"]
+----
+@Bean
+fun httpFirewall(): StrictHttpFirewall {
+    val firewall = StrictHttpFirewall()
+    firewall.setAllowedHeaderNames { true }
+    firewall.setAllowedHeaderValues { true }
+    firewall.setAllowedParameterNames { true }
+    return firewall
+}
+----
+====
+
+Or, there might be a specific value that you need to allow.
+
+For example, iPhone Xʀ uses a `User-Agent` that includes a character not in the ISO-8859-1 charset.
+Due to this fact, some application servers will parse this value into two separate characters, the latter being an undefined character.
+
+You can address this with the `setAllowedHeaderValues` method, as you can see below:
+
+.Allow Certain User Agents
+====
+.Java
+[source,java,role="primary"]
+----
+@Bean
+public StrictHttpFirewall httpFirewall() {
+    StrictHttpFirewall firewall = new StrictHttpFirewall();
+    Pattern allowed = Pattern.compile("[\\p{IsAssigned}&&[^\\p{IsControl}]]*");
+    Pattern userAgent = ...;
+    firewall.setAllowedHeaderValues((header) -> allowed.matcher(header).matches() || userAgent.matcher(header).matches());
+    return firewall;
+}
+----
+
+.Kotlin
+[source,kotlin,role="secondary"]
+----
+@Bean
+fun httpFirewall(): StrictHttpFirewall {
+    val firewall = StrictHttpFirewall()
+    val allowed = Pattern.compile("[\\p{IsAssigned}&&[^\\p{IsControl}]]*")
+    val userAgent = Pattern.compile(...)
+    firewall.setAllowedHeaderValues { allowed.matcher(it).matches() || userAgent.matcher(it).matches() }
+    return firewall
+}
+----
+====
+
+In the case of header values, you may instead consider parsing them as UTF-8 at verification time like so:
+
+.Parse Headers As UTF-8
+====
+.Java
+[source,java,role="primary"]
+----
+firewall.setAllowedHeaderValues((header) -> {
+    String parsed = new String(header.getBytes(ISO_8859_1), UTF_8);
+    return allowed.matcher(parsed).matches();
+});
+----
+
+.Kotlin
+[source,kotlin,role="secondary"]
+----
+firewall.setAllowedHeaderValues {
+    val parsed = String(header.getBytes(ISO_8859_1), UTF_8)
+    return allowed.matcher(parsed).matches()
+}
+----
+====