Răsfoiți Sursa

SEC-2498: RequestCache allows POST when CSRF is disabled

Rob Winch 11 ani în urmă
părinte
comite
cb0549a609

+ 17 - 2
config/src/main/java/org/springframework/security/config/annotation/web/configurers/RequestCacheConfigurer.java

@@ -15,7 +15,9 @@
  */
 package org.springframework.security.config.annotation.web.configurers;
 
+import java.util.ArrayList;
 import java.util.Collections;
+import java.util.List;
 
 import org.springframework.http.MediaType;
 import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
@@ -114,12 +116,13 @@ public final class RequestCacheConfigurer<H extends HttpSecurityBuilder<H>> exte
         return defaultCache;
     }
 
+    @SuppressWarnings("unchecked")
     private RequestMatcher createDefaultSavedRequestMatcher(H http) {
         ContentNegotiationStrategy contentNegotiationStrategy = http.getSharedObject(ContentNegotiationStrategy.class);
         if(contentNegotiationStrategy == null) {
             contentNegotiationStrategy = new HeaderContentNegotiationStrategy();
         }
-        RequestMatcher getRequests = new AntPathRequestMatcher("/**", "GET");
+
         RequestMatcher notFavIcon = new NegatedRequestMatcher(new AntPathRequestMatcher("/**/favicon.ico"));
 
         MediaTypeRequestMatcher jsonRequest = new MediaTypeRequestMatcher(contentNegotiationStrategy, MediaType.APPLICATION_JSON);
@@ -127,6 +130,18 @@ public final class RequestCacheConfigurer<H extends HttpSecurityBuilder<H>> exte
         RequestMatcher notJson = new NegatedRequestMatcher(jsonRequest);
 
         RequestMatcher notXRequestedWith = new NegatedRequestMatcher(new RequestHeaderRequestMatcher("X-Requested-With","XMLHttpRequest"));
-        return new AndRequestMatcher(getRequests, notFavIcon, notJson, notXRequestedWith);
+
+        boolean isCsrfEnabled = http.getConfigurer(CsrfConfigurer.class) != null;
+
+        List<RequestMatcher> matchers = new ArrayList<RequestMatcher>();
+        if(isCsrfEnabled) {
+            RequestMatcher getRequests = new AntPathRequestMatcher("/**", "GET");
+            matchers.add(0, getRequests);
+        }
+        matchers.add(notFavIcon);
+        matchers.add(notJson);
+        matchers.add(notXRequestedWith);
+
+        return new AndRequestMatcher(matchers);
     }
 }

+ 43 - 0
config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/CsrfConfigurerTests.groovy

@@ -102,6 +102,49 @@ class CsrfConfigurerTests extends BaseSpringSpec {
         }
     }
 
+    def "SEC-2498: Disable CSRF enables RequestCache for any method"() {
+        setup:
+            loadConfig(DisableCsrfEnablesRequestCacheConfig)
+            request.requestURI = '/tosave'
+            request.method = "POST"
+            clearCsrfToken()
+        when:
+            springSecurityFilterChain.doFilter(request,response,chain)
+        then:
+            response.redirectedUrl
+        when:
+            super.setupWeb(request.session)
+            request.method = "POST"
+            request.servletPath = '/login'
+            request.parameters['username'] = ['user'] as String[]
+            request.parameters['password'] = ['password'] as String[]
+            springSecurityFilterChain.doFilter(request,response,chain)
+        then:
+            response.redirectedUrl == 'http://localhost/tosave'
+    }
+
+    @Configuration
+    @EnableWebSecurity
+    static class DisableCsrfEnablesRequestCacheConfig extends WebSecurityConfigurerAdapter {
+
+        @Override
+        protected void configure(HttpSecurity http) throws Exception {
+            http
+                .authorizeRequests()
+                    .anyRequest().authenticated()
+                    .and()
+                .formLogin().and()
+                .csrf().disable()
+
+        }
+        @Override
+        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+            auth
+                .inMemoryAuthentication()
+                    .withUser("user").password("password").roles("USER")
+        }
+    }
+
     def "SEC-2422: csrf expire CSRF token and session-management invalid-session-url"() {
         setup:
             loadConfig(InvalidSessionUrlConfig)