Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Security, trailing slashes, and dots in URLs

I use Spring Security 3.1.4 to secure a Spring MVC 3.2.4 application deployed to Tomcat. I have the following Spring Security configuration:

<http auto-config="true" use-expressions="true">
   <http-basic />
   <logout ... />
   <form-login ... />

   <intercept-url pattern="/" access="isAnonymous() or hasRole('ROLE_USER')" />
   <intercept-url pattern="/about" access="isAnonymous() or hasRole('ROLE_USER')" />
   <intercept-url pattern="/login" access="isAnonymous() or hasRole('ROLE_USER')" />
   <intercept-url pattern="/under-construction" access="isAnonymous() or hasRole('ROLE_USER')" />
   <intercept-url pattern="/admin-task*" access="hasRole('ROLE_USER') and hasRole('ROLE_ADMINISTRATOR')" />
   <intercept-url pattern="/resources/**" access="isAnonymous() or hasRole('ROLE_USER')" />
   <intercept-url pattern="/**" access="hasRole('ROLE_USER')" />
</http>

I noticed that URL patterns without a trailing slash (e.g., /about) do not match URLs with a trailing slash (e.g., /about/) and vice-versa. In other words, a URL with a slash and an identical URL without a slash are treated as two different URLs by Spring Security. The problem could be fixed by using two security rules:

<intercept-url pattern="/about" access="isAnonymous() or hasRole('ROLE_USER')" />
<intercept-url pattern="/about/" access="isAnonymous() or hasRole('ROLE_USER')" />

Is there a better solution?

I know that path-type="regex" allows to define URL patterns with regular expressions, but I would like to avoid any unnecessary complexity if it's possible.

Update

As Adam Gent noted, there is an additional problem that involves URLs with a dot: /about.foo and /about are treated as the same URL by Spring MVC. However, Spring Security treats them as two different URLs. So, one more security rule may be necessary:

<intercept-url pattern="/about.*" .../>
like image 286
Alexey Avatar asked Dec 15 '13 03:12

Alexey


2 Answers

Spring Security 4.1+

Spring Security has now added a new matcher which is aware of your Spring MVC URL matching configuration. This tells Spring Security to match paths based on the same rules that Spring MVC uses, eliminating the possibility of a URL being valid, but unsecured.

First you need to replace any old matchers with the new MVC matcher. Spring Security is now in sync with however you have configured Spring MVC so you are free to add or remove any path matching configuration. I recommend sticking with the defaults where possible.

Java Config

If you were using antMatchers, you now should use mvcMatchers:

protected configure(HttpSecurity http) throws Exception {
  http.authorizeRequests()
        .mvcMatchers("/about").hasRole("USER");
}

XML Config

You need to add the attribute request-matcher to your http tag:

<http request-matcher="mvc">
  <intercept-url pattern="/about" access="hasRole('USER')"/>
</http>

Full Reference

Please note that you also should no longer be prefixing your roles with "ROLE_" as Spring Security does this for you automatically.


Spring Security Before 4.1

I've not been able to find a way to handle both trailing slash and path suffixes in Spring Security. Obviously it is possible to write a regexp to handle these cases but this seems to make the security rules overly complex and prone to error. I want to be as confident as possible that I'm not exposing resources accidentally.

Therefore, my approach is to disable this behaviour in Spring by configuring the path matcher to be strict about both trailing slashes and suffixes.

Java Config

@Configuration
public class ServletConfig extends WebMvcConfigurerAdapter {
  @Override
  public void configurePathMatch(final PathMatchConfigurer configurer) {
    configurer.setUseSuffixPatternMatch(false);
    configurer.setUseTrailingSlashMatch(false);
  }
}

XML Config

<mvc:annotation-driven>
  <mvc:path-matching suffix-pattern="false" trailing-slash="false" />
</mvc:annotation-driven>
like image 189
Rupert Madden-Abbott Avatar answered Sep 22 '22 20:09

Rupert Madden-Abbott


<intercept-url pattern="/about/**"...

also works for me in Spring Security 3.1.4. This secures /about, /about/, and /about/anything_else

like image 34
Evgeni Dimitrov Avatar answered Sep 21 '22 20:09

Evgeni Dimitrov