spring-projects / spring-security

Spring Security
http://spring.io/projects/spring-security
Apache License 2.0
8.79k stars 5.9k forks source link

SEC-1658: JA-SIG CAS Single Sign Out feature conflict with session-fixation protection #1897

Closed spring-projects-issues closed 3 years ago

spring-projects-issues commented 13 years ago

DUBOIS Fabrice (Migrated from SEC-1658) said:

I run into problems with CAS Single Sign Out feature working with session-fixation protection feature.

Indeed, Spring Security ConcurrentSessionControlStrategy always invalidate the existing session (call of session.invalidate( )) and create a new one to prevent from session-fixation attacks.

So, after CAS login process, SingleSignOutHttpSessionListener.sessionDestroyed( ) is called causing "ST to original session mapping" to be removed from SingleSignOutFilter's SESSION_MAPPING_STORAGE member.

When a single sign out request is posted, the new session isn't invalidated because "ST to new session mapping" was never been registered in SingleSingOutFilter's SESSION_MAPPING_STORAGE member.

spring-projects-issues commented 13 years ago

Luke Taylor said:

I don't really think this is a major bug in Spring Security's current code. What you are saying is that if you choose to use session-fixation protection then this is not compatible with the use of CAS single sign-out which assumes that the session is never changed after authenticating.

Any external service could implement HttpSessionListener.sessionDestroyed(), making the assumption that the event means the user has logged out. In each case, this would require custom behaviour to be injected to override that assumption. In this case, it would probably mean calling the SessionMappingStorage instance used by the SSO filter in order to add the new session.

spring-projects-issues commented 13 years ago

DUBOIS Fabrice said:

If I understand, this means that I should intercept sessionCreated() event, request another Service Ticket (ST) from CAS and store in SessionMappingStorage the "ST to new session mapping" ?

For the moment, SingleSignOutHttpSessionListener's sessionCreated() method does nothing :

public final class SingleSignOutHttpSessionListener implements HttpSessionListener {

private SessionMappingStorage SESSION_MAPPING_STORAGE;

public void sessionCreated(final HttpSessionEvent event) {
    // nothing to do at the moment
}

....

spring-projects-issues commented 13 years ago

Luke Taylor said:

I don't think it should be necessary to request another ST. The existing ST should be available as the credentials property of the CasAuthenticationToken, so if you customize the SessionAuthenticationStrategy to do something like

sessionMappingStorage.addSessionById((String)authentication.getCredentials(), newSession);

This should make sure that the new session is stored in the SSO filter's registry, and when a logout request arrives for that ST, it will invalidate the new session.

spring-projects-issues commented 13 years ago

DUBOIS Fabrice said:

I agree with you but this solution implies that :

spring-projects-issues commented 13 years ago

Luke Taylor said:

I'm not really sure what you mean here - SessionMappingStorage is a static variable and is accessible through SingleSignOutFilter.getSessionMappingStorage(). So you have full access to it.

Alternatively you can inject the implementation into the filter yourself and retain a reference for use elsewhere.

I would expect that the filter would come before the Spring Security filters. The sequence would be

  1. It eagerly creates a session if one doesn't already exist and adds an entry using the ticket Id and the current session
  2. Spring Security's CasAuthenticationFilter authenticates using the ticket
  3. The SessionAuthenticationStrategy is called
  4. It invalidates the session (causing it to be removed from the store). Either that or you could do this explicitly yourself, rather than relying on the listener.
  5. It creates a new session.
  6. You call addSessionById to store the new session.
spring-projects-issues commented 13 years ago

DUBOIS Fabrice said:

Just to be sure (as far I could understand) :

  1. It = SingleSigneOutFilter
  2. It = SessionManagementFilter in relation with SessionAuthenticationStrategy
  3. It = SessionManagementFilter in relation with SessionAuthenticationStrategy
  4. SessionAuthenticationStrategy

Right ?

spring-projects-issues commented 13 years ago

Luke Taylor said:

No. SessionManagementFilter would not be involved, since a redirect is performed from the authentication filter. 4,5 and 6 are all part of your SessionAuthenticationStrategy .

spring-projects-issues commented 11 years ago

roll tide said:

Hi Dubois - Did this work for you with the suggestions provided? I am running to this issue as well so wanted to check if suggested fix worked for you?

spring-projects-issues commented 11 years ago

Mike Argyriou said:

@DUBOIS Fabrice: I have faced the same problem in my application using CAS (Jasig) (not spring or spring security involved). I am just commenting to thank you for your observation; same happened on my custom app. On login action (using struts) there was a line session.invalidate() which fired an event that called org.jasig.cas.client.session.SingleSignOutHttpSessionListener#sessionDestroyed() which in turn called sessionMappingStorage.removeBySessionById(session.getId()). Therefore org.jasig.cas.client.session#handler#sessionMappingStorage was always empty! The solution was to comment (or remove) session.invalidate() in login action.

spring-projects-issues commented 9 years ago

Hugo Francisco Baes Junior said:

I managed to solve this issue using a custom SSO Filter that checks if the request is a ticket validation (like SSOHandler.isTokenRequest) before delegating to SSOHandler. If it is, then I call the filterChain.doFilter() first, so CasAuthenticationFilter/SuccessHandler may renew the SessionID , and after that I let SSOHandler proccess properly the request with the actual SessionID.

jgribonvald commented 8 years ago

Thanks for the tip this helped me a lot !

Just one other tip : you need to update authentication details on implementing a custom SessionFixatgionProtectionStrategy else you keep in authentication object the old sessionId (not totaly usefull, it's only for logging event that used this object)

rwinch commented 3 years ago

This should be changed in CAS rather than Spring Security

nchava1 commented 8 months ago

Hi. How this was fixed? I see same issue on spring 5.x and cas server 6.5.4 and cas client 3.1.12.

Thanks