21
votes

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?

3
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"/>Крис

3 Answers

40
votes

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!

7
votes

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.

0
votes

I used combination of following two

  1. https://stackoverflow.com/a/48636757/6780127
  2. https://stackoverflow.com/a/30539991/6780127

  • 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);
}