StrictHttpFirewall in spring security 4.2 vs spring MVC @MatrixVariable
Asked Answered
P

3

23

Having upgraded to spring security 4.2.4 I discovered that StrictHttpFirewall is now the default. Unfortunately it doesn't play well with spring MVC @MatrixVariable since ";" are not allowed anymore. How to get around that?

Example:

@GetMapping(path = "/{param}")
public void example(@PathVariable String param,
                    @MatrixVariable Map<String, String> matrix) {
    //...
}

This could be called like this:

mockMvc.perform(get("/someparam;key=value"))

And the matrix map would be populated. Now spring security blocks it.

org.springframework.security.web.firewall.RequestRejectedException: The request was rejected because the URL contained a potentially malicious String ";"

at org.springframework.security.web.firewall.StrictHttpFirewall.rejectedBlacklistedUrls(StrictHttpFirewall.java:140)

I could use a custom HttpFirewall that would allow semicolons. Is there a way to use @MatrixVariable without using forbidden characters?

BTW: the javadoc is incorrect https://docs.spring.io/autorepo/docs/spring-security/4.2.x/apidocs/index.html?org/springframework/security/web/firewall/StrictHttpFirewall.html

Since:

5.0.1

I guess it was backported?

Purdah answered 2/2, 2018 at 10:23 Comment(1)
Here is how to allow semicolons: <bean id="myHttpFirewall" class="org.springframework.security.web.firewall.StrictHttpFirewall"> <property name="allowSemicolon" value="true"/> </bean> <security:http-firewall ref="myHttpFirewall"/>Maladjusted
L
42

You can dilute the default spring security firewall using your custom defined instance of StrictHttpFirewall (at your own risk)

@Bean
public HttpFirewall allowUrlEncodedSlashHttpFirewall() {
    StrictHttpFirewall firewall = new StrictHttpFirewall();
    firewall.setAllowUrlEncodedSlash(true);
    firewall.setAllowSemicolon(true);
    return firewall;
}

And then use this custom firewall bean in WebSecurity (Spring boot does not need this change)

@Override
public void configure(WebSecurity web) throws Exception {
  super.configure(web);
  // @formatter:off
  web.httpFirewall(allowUrlEncodedSlashHttpFirewall());
...
}

That shall work with Spring Security 4.2.4+, but of-course that brings some risks!

Lenticel answered 6/2, 2018 at 6:27 Comment(8)
The StrictHttpFirewall blocks the request because it is dangerous to allow them. Due to ambiguities in the Servlet specification and inconsistent behavior between Servlet Containers short of rejecting URL encoded semicolons we haven't been able to find a good way to protect against such exploits.Georgie
Then Spring MVC @MatrixVariable must be changed as well.Maladjusted
For some reason it doesn't work with Spring Security 5.0.3.RELEASE.Gough
@RobWinch yes, blocking the request is a good idea, but I've found that spring is internally adding a // in some cases jira.spring.io/browse/SPR-16740Colfin
Wiring the bean in the configure(WebSecurity web) method should not be necessary since the WebSecurity instance tries to find beans of type HttpFirewall in the context by using the ApplicationContextAware annotation. In other words, just instantiating a bean of type HttpFirewall should be enough.Joacimah
Another option is to subclass HttpStrictFirewall to gain some control over which requests are rejected, as detailed in this answer.Ance
What is the risk? Can somebody explain me why this would be necessary?Laris
The risks are described in the javadoc of Spring Security StrictHttpFirewall.setAllowSemicolon docs.spring.io/spring-security/site/docs/current/api/org/…Maladjusted
T
8

As mentioned by Крис in a comment if you prefer to use a XML approach, you can add the following part to your securityContext.xml (or whatever your spring-security related xml-config is called):

<bean id="allowSemicolonHttpFirewall" 
      class="org.springframework.security.web.firewall.StrictHttpFirewall"> 
        <property name="allowSemicolon" value="true"/> 
</bean> 
<security:http-firewall ref="allowSemicolonHttpFirewall"/>

The <bean> part defines a new StrictHttpFirewall bean with the id allowSemicolonHttpFirewall which is then set as default http-firewall in the <security> tag by referencing the id.

Toluol answered 8/3, 2019 at 18:21 Comment(0)
L
0

I used combination of following two

  1. https://mcmap.net/q/18293/-stricthttpfirewall-in-spring-security-4-2-vs-spring-mvc-matrixvariable
  2. https://mcmap.net/q/18462/-spring-mvc-missing-matrix-variable

  • First one resolved the The request was rejected because the URL contained a potentially malicious String ";"
  • Second one Resolved the Spring MVC Missing matrix variable

As I am using Spring Security with Spring Web I had to do both And the issue is now Resolved.

I found using @MatrixVariable Following Pattern is useful. First in Url {num} has to be mentioned to use it as @MatrixVariable

@RequestMapping(method = RequestMethod.GET,value = "/test{num}")
@ResponseBody
public ResponseEntity<String> getDetail(@MatrixVariable String num){
    return new ResponseEntity<>("test"+num, HttpStatus.OK);
}
Lashondalashonde answered 12/5, 2019 at 11:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.