Merge branch '5.8.x'
# Conflicts: # docs/modules/ROOT/pages/servlet/exploits/csrf.adoc
This commit is contained in:
+45
-2
@@ -48,6 +48,7 @@ import org.springframework.security.web.csrf.CsrfTokenRequestAttributeHandler;
|
||||
import org.springframework.security.web.csrf.CsrfTokenRequestHandler;
|
||||
import org.springframework.security.web.csrf.DefaultCsrfToken;
|
||||
import org.springframework.security.web.csrf.DeferredCsrfToken;
|
||||
import org.springframework.security.web.csrf.XorCsrfTokenRequestAttributeHandler;
|
||||
import org.springframework.security.web.firewall.StrictHttpFirewall;
|
||||
import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
|
||||
import org.springframework.security.web.savedrequest.RequestCache;
|
||||
@@ -64,6 +65,7 @@ import org.springframework.web.servlet.support.RequestDataValueProcessor;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.isNull;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
@@ -429,7 +431,7 @@ public class CsrfConfigurerTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getLoginWhenCsrfTokenRequestHandlerSetThenRespondsWithNormalCsrfToken() throws Exception {
|
||||
public void getLoginWhenCsrfTokenRequestAttributeHandlerSetThenRespondsWithNormalCsrfToken() throws Exception {
|
||||
CsrfTokenRepository csrfTokenRepository = mock(CsrfTokenRepository.class);
|
||||
CsrfToken csrfToken = new DefaultCsrfToken("X-CSRF-TOKEN", "_csrf", "token");
|
||||
given(csrfTokenRepository.loadDeferredToken(any(HttpServletRequest.class), any(HttpServletResponse.class)))
|
||||
@@ -444,7 +446,7 @@ public class CsrfConfigurerTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loginWhenCsrfTokenRequestHandlerSetAndNormalCsrfTokenThenSuccess() throws Exception {
|
||||
public void loginWhenCsrfTokenRequestAttributeHandlerSetAndNormalCsrfTokenThenSuccess() throws Exception {
|
||||
CsrfToken csrfToken = new DefaultCsrfToken("X-CSRF-TOKEN", "_csrf", "token");
|
||||
CsrfTokenRepository csrfTokenRepository = mock(CsrfTokenRepository.class);
|
||||
given(csrfTokenRepository.loadDeferredToken(any(HttpServletRequest.class), any(HttpServletResponse.class)))
|
||||
@@ -466,6 +468,47 @@ public class CsrfConfigurerTests {
|
||||
verifyNoMoreInteractions(csrfTokenRepository);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getLoginWhenXorCsrfTokenRequestAttributeHandlerSetThenRespondsWithMaskedCsrfToken() throws Exception {
|
||||
CsrfTokenRepository csrfTokenRepository = mock(CsrfTokenRepository.class);
|
||||
CsrfToken csrfToken = new DefaultCsrfToken("X-CSRF-TOKEN", "_csrf", "token");
|
||||
given(csrfTokenRepository.loadDeferredToken(any(HttpServletRequest.class), any(HttpServletResponse.class)))
|
||||
.willReturn(new TestDeferredCsrfToken(csrfToken));
|
||||
CsrfTokenRequestHandlerConfig.REPO = csrfTokenRepository;
|
||||
CsrfTokenRequestHandlerConfig.HANDLER = new XorCsrfTokenRequestAttributeHandler();
|
||||
this.spring.register(CsrfTokenRequestHandlerConfig.class, BasicController.class).autowire();
|
||||
this.mvc.perform(get("/login")).andExpect(status().isOk())
|
||||
.andExpect(content().string(not(containsString(csrfToken.getToken()))));
|
||||
verify(csrfTokenRepository).loadDeferredToken(any(HttpServletRequest.class), any(HttpServletResponse.class));
|
||||
verifyNoMoreInteractions(csrfTokenRepository);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loginWhenXorCsrfTokenRequestAttributeHandlerSetAndMaskedCsrfTokenThenSuccess() throws Exception {
|
||||
CsrfToken csrfToken = new DefaultCsrfToken("X-CSRF-TOKEN", "_csrf", "token");
|
||||
CsrfTokenRepository csrfTokenRepository = mock(CsrfTokenRepository.class);
|
||||
given(csrfTokenRepository.loadDeferredToken(any(HttpServletRequest.class), any(HttpServletResponse.class)))
|
||||
.willReturn(new TestDeferredCsrfToken(csrfToken));
|
||||
CsrfTokenRequestHandlerConfig.REPO = csrfTokenRepository;
|
||||
CsrfTokenRequestHandlerConfig.HANDLER = new XorCsrfTokenRequestAttributeHandler();
|
||||
this.spring.register(CsrfTokenRequestHandlerConfig.class, BasicController.class).autowire();
|
||||
|
||||
MvcResult mvcResult = this.mvc.perform(get("/login")).andReturn();
|
||||
CsrfToken csrfTokenAttribute = (CsrfToken) mvcResult.getRequest().getAttribute(CsrfToken.class.getName());
|
||||
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder loginRequest = post("/login")
|
||||
.header(csrfToken.getHeaderName(), csrfTokenAttribute.getToken())
|
||||
.param("username", "user")
|
||||
.param("password", "password");
|
||||
// @formatter:on
|
||||
this.mvc.perform(loginRequest).andExpect(redirectedUrl("/"));
|
||||
verify(csrfTokenRepository).saveToken(isNull(), any(HttpServletRequest.class), any(HttpServletResponse.class));
|
||||
verify(csrfTokenRepository, times(3)).loadDeferredToken(any(HttpServletRequest.class),
|
||||
any(HttpServletResponse.class));
|
||||
verifyNoMoreInteractions(csrfTokenRepository);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class AllowHttpMethodsFirewallConfig {
|
||||
|
||||
|
||||
@@ -300,6 +300,39 @@ public class CsrfConfigTests {
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void postWhenUsingCsrfAndXorCsrfTokenRequestProcessorThenOk() throws Exception {
|
||||
this.spring.configLocations(this.xml("WithXorCsrfTokenRequestAttributeHandler"), this.xml("shared-controllers"))
|
||||
.autowire();
|
||||
// @formatter:off
|
||||
MvcResult mvcResult = this.mvc.perform(get("/ok"))
|
||||
.andExpect(status().isOk())
|
||||
.andReturn();
|
||||
MockHttpSession session = (MockHttpSession) mvcResult.getRequest().getSession();
|
||||
CsrfToken csrfToken = (CsrfToken) mvcResult.getRequest().getAttribute("_csrf");
|
||||
MockHttpServletRequestBuilder ok = post("/ok")
|
||||
.header(csrfToken.getHeaderName(), csrfToken.getToken())
|
||||
.session(session);
|
||||
this.mvc.perform(ok).andExpect(status().isOk());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void postWhenUsingCsrfAndXorCsrfTokenRequestProcessorWithRawTokenThenForbidden() throws Exception {
|
||||
this.spring.configLocations(this.xml("WithXorCsrfTokenRequestAttributeHandler"), this.xml("shared-controllers"))
|
||||
.autowire();
|
||||
// @formatter:off
|
||||
MvcResult mvcResult = this.mvc.perform(get("/ok"))
|
||||
.andExpect(status().isOk())
|
||||
.andReturn();
|
||||
MockHttpSession session = (MockHttpSession) mvcResult.getRequest().getSession();
|
||||
MockHttpServletRequestBuilder ok = post("/ok")
|
||||
.with(csrf())
|
||||
.session(session);
|
||||
this.mvc.perform(ok).andExpect(status().isForbidden());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void postWhenHasCsrfTokenButSessionExpiresThenRequestIsCancelledAfterSuccessfulAuthentication()
|
||||
throws Exception {
|
||||
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ Copyright 2002-2018 the original author or authors.
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ https://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
|
||||
<b:beans xmlns:b="http://www.springframework.org/schema/beans"
|
||||
xmlns:p="http://www.springframework.org/schema/p"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://www.springframework.org/schema/security"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/security https://www.springframework.org/schema/security/spring-security.xsd
|
||||
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
<http auto-config="true">
|
||||
<csrf request-handler-ref="requestHandler"/>
|
||||
</http>
|
||||
|
||||
<b:bean id="requestHandler" class="org.springframework.security.web.csrf.XorCsrfTokenRequestAttributeHandler"
|
||||
p:csrfRequestAttributeName="_csrf"/>
|
||||
<b:import resource="CsrfConfigTests-shared-userservice.xml"/>
|
||||
</b:beans>
|
||||
Reference in New Issue
Block a user