1
0
mirror of synced 2026-08-05 17:57:15 +00:00

SEC-834: Session fixation attack protection will cause problems with URL rewriting

http://jira.springframework.org/browse/SEC-834. Changed position of SessionFixationProtectionFilter and modified it to make a decision about whether authentication has taken place prior to calling doFilter(). Previously it did this on the return through the filter chain, which caused the problem described in this issue.
This commit is contained in:
Luke Taylor
2008-05-15 00:26:27 +00:00
parent 7f38c656ca
commit d17a2da9e0
4 changed files with 38 additions and 194 deletions
@@ -96,8 +96,7 @@ public class HttpSecurityBeanDefinitionParserTests {
Iterator filters = filterList.iterator();
assertTrue(filters.next() instanceof HttpSessionContextIntegrationFilter);
assertTrue(filters.next() instanceof SessionFixationProtectionFilter);
assertTrue(filters.next() instanceof HttpSessionContextIntegrationFilter);
assertTrue(filters.next() instanceof LogoutFilter);
Object authProcFilter = filters.next();
assertTrue(authProcFilter instanceof AuthenticationProcessingFilter);
@@ -112,6 +111,7 @@ public class HttpSecurityBeanDefinitionParserTests {
assertTrue(filters.next() instanceof RememberMeProcessingFilter);
assertTrue(filters.next() instanceof AnonymousProcessingFilter);
assertTrue(filters.next() instanceof ExceptionTranslationFilter);
assertTrue(filters.next() instanceof SessionFixationProtectionFilter);
Object fsiObj = filters.next();
assertTrue(fsiObj instanceof FilterSecurityInterceptor);
FilterSecurityInterceptor fsi = (FilterSecurityInterceptor) fsiObj;
@@ -173,7 +173,7 @@ public class HttpSecurityBeanDefinitionParserTests {
" <form-login default-target-url='/default' always-use-default-target='true' />" +
"</http>" + AUTH_PROVIDER_XML);
// These will be matched by the default pattern "/**"
AuthenticationProcessingFilter filter = (AuthenticationProcessingFilter) getFilters("/anything").get(2);
AuthenticationProcessingFilter filter = (AuthenticationProcessingFilter) getFilters("/anything").get(1);
assertEquals("/default", filter.getDefaultTargetUrl());
assertEquals(Boolean.TRUE, FieldUtils.getFieldValue(filter, "alwaysUseDefaultTargetUrl"));
}
@@ -264,7 +264,7 @@ public class HttpSecurityBeanDefinitionParserTests {
setContext("<http access-denied-page='/access-denied'><http-basic /></http>" + AUTH_PROVIDER_XML);
List filters = getFilters("/someurl");
ExceptionTranslationFilter etf = (ExceptionTranslationFilter) filters.get(filters.size() - 2);
ExceptionTranslationFilter etf = (ExceptionTranslationFilter) filters.get(filters.size() - 3);
assertEquals("/access-denied", FieldUtils.getFieldValue(etf, "accessDeniedHandler.errorPage"));
}
@@ -324,7 +324,7 @@ public class HttpSecurityBeanDefinitionParserTests {
assertEquals(14, filters.size());
assertTrue(filters.get(0) instanceof MockFilter);
assertTrue(filters.get(1) instanceof SecurityContextHolderAwareRequestFilter);
assertTrue(filters.get(5) instanceof SecurityContextHolderAwareRequestFilter);
assertTrue(filters.get(4) instanceof SecurityContextHolderAwareRequestFilter);
}
@Test(expected=BeanCreationException.class)
@@ -368,7 +368,7 @@ public class HttpSecurityBeanDefinitionParserTests {
"</http>" + AUTH_PROVIDER_XML);
List filters = getFilters("/someurl");
assertTrue(filters.get(3) instanceof X509PreAuthenticatedProcessingFilter);
assertTrue(filters.get(2) instanceof X509PreAuthenticatedProcessingFilter);
}
@Test
@@ -422,7 +422,7 @@ public class HttpSecurityBeanDefinitionParserTests {
"<b:bean id='entryPoint' class='org.springframework.security.MockAuthenticationEntryPoint'>" +
" <b:constructor-arg value='/customlogin'/>" +
"</b:bean>" + AUTH_PROVIDER_XML);
ExceptionTranslationFilter etf = (ExceptionTranslationFilter) getFilters("/someurl").get(9);
ExceptionTranslationFilter etf = (ExceptionTranslationFilter) getFilters("/someurl").get(8);
assertTrue("ExceptionTranslationFilter should be configured with custom entry point",
etf.getAuthenticationEntryPoint() instanceof MockAuthenticationEntryPoint);
}
@@ -2,19 +2,14 @@ package org.springframework.security.ui;
import static org.junit.Assert.*;
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.junit.After;
import org.junit.Test;
import org.springframework.mock.web.MockFilterChain;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.security.context.HttpSessionContextIntegrationFilter;
import org.springframework.security.context.SecurityContextHolder;
import org.springframework.security.providers.TestingAuthenticationToken;
@@ -34,6 +29,7 @@ public class SessionFixationProtectionFilterTests {
public void newSessionShouldNotBeCreatedIfNoSessionExists() throws Exception {
SessionFixationProtectionFilter filter = new SessionFixationProtectionFilter();
HttpServletRequest request = new MockHttpServletRequest();
authenticateUser();
filter.doFilter(request, new MockHttpServletResponse(), new MockFilterChain());
@@ -41,14 +37,15 @@ public class SessionFixationProtectionFilterTests {
}
@Test
public void newSessionShouldNotBeCreatedIfUserIsAuthenticated() throws Exception {
public void newSessionBeCreatedIfAuthenticatedOccurredDuringRequest() throws Exception {
SessionFixationProtectionFilter filter = new SessionFixationProtectionFilter();
HttpServletRequest request = new MockHttpServletRequest();
String sessionId = request.getSession().getId();
authenticateUser();
filter.doFilter(request, new MockHttpServletResponse(), new MockFilterChain());
assertEquals(sessionId, request.getSession().getId());
assertFalse(sessionId.equals(request.getSession().getId()));
}
@Test
@@ -68,91 +65,15 @@ public class SessionFixationProtectionFilterTests {
HttpServletRequest request = new MockHttpServletRequest();
String sessionId = request.getSession().getId();
authenticateUser();
request.getSession().setAttribute(HttpSessionContextIntegrationFilter.SPRING_SECURITY_CONTEXT_KEY,
SecurityContextHolder.getContext());
filter.doFilter(request, new MockHttpServletResponse(), new MockFilterChain());
assertEquals(sessionId, request.getSession().getId());
}
@Test
public void newSessionShouldBeCreatedIfAuthenticationOccursDuringRequest() throws Exception {
SessionFixationProtectionFilter filter = new SessionFixationProtectionFilter();
HttpServletRequest request = new MockHttpServletRequest();
String sessionId = request.getSession().getId();
filter.doFilter(request, new MockHttpServletResponse(), new UserAuthenticatingFilterChain());
assertFalse(sessionId.equals(request.getSession().getId()));
}
@Test
public void newSessionShouldBeCreatedIfAuthenticationAndRedirectOccursDuringRequest() throws Exception {
SessionFixationProtectionFilter filter = new SessionFixationProtectionFilter();
HttpServletRequest request = new MockHttpServletRequest();
String sessionId = request.getSession().getId();
AuthenticateAndRedirectFilterChain chain = new AuthenticateAndRedirectFilterChain();
filter.doFilter(request, new MockHttpServletResponse(), chain);
assertTrue(chain.getResponse() instanceof
SessionFixationProtectionFilter.SessionFixationProtectionResponseWrapper);
assertTrue("New session should have been created by session wrapper",
((SessionFixationProtectionFilter.SessionFixationProtectionResponseWrapper)chain.getResponse()).isNewSessionStarted());
assertFalse(sessionId.equals(request.getSession().getId()));
}
@Test
public void wrapperSendErrorCreatesNewSession() throws Exception {
authenticateUser();
SessionFixationProtectionFilter filter = new SessionFixationProtectionFilter();
HttpServletRequest request = new MockHttpServletRequest();
String sessionId = request.getSession().getId();
SessionFixationProtectionFilter.SessionFixationProtectionResponseWrapper wrapper =
filter.new SessionFixationProtectionResponseWrapper(new MockHttpServletResponse(), request);
wrapper.sendError(HttpServletResponse.SC_FORBIDDEN);
assertFalse(sessionId.equals(request.getSession().getId()));
// Message version
request = new MockHttpServletRequest();
sessionId = request.getSession().getId();
wrapper = filter.new SessionFixationProtectionResponseWrapper(new MockHttpServletResponse(), request);
wrapper.sendError(HttpServletResponse.SC_FORBIDDEN, "Hi. I'm your friendly forbidden message.");
assertFalse(sessionId.equals(request.getSession().getId()));
}
@Test
public void wrapperRedirectCreatesNewSession() throws Exception {
authenticateUser();
SessionFixationProtectionFilter filter = new SessionFixationProtectionFilter();
HttpServletRequest request = new MockHttpServletRequest();
String sessionId = request.getSession().getId();
SessionFixationProtectionFilter.SessionFixationProtectionResponseWrapper wrapper =
filter.new SessionFixationProtectionResponseWrapper(new MockHttpServletResponse(), request);
wrapper.sendRedirect("/somelocation");
assertFalse(sessionId.equals(request.getSession().getId()));
}
private void authenticateUser() {
SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken("user", "pass", null));
}
private class UserAuthenticatingFilterChain implements FilterChain {
public void doFilter(ServletRequest request, ServletResponse response) throws IOException {
authenticateUser();
}
}
private class AuthenticateAndRedirectFilterChain extends UserAuthenticatingFilterChain{
HttpServletResponse response;
public void doFilter(ServletRequest request, ServletResponse response) throws IOException {
super.doFilter(request, response);
this.response = (HttpServletResponse)response;
this.response.sendRedirect("/someUrl");
}
public HttpServletResponse getResponse() {
return response;
}
}
}