Session fixation in Spring Security - spring

We are trying to prevent session fixation attack in our application. This means we are expected to generate new JSESSIONID every time a user logs into application.
Current scenario doesn't generate new JSESSIONID post authentication with ADFS (Active directory). Thus we would like to achieve the same. Can you let us know, how to achieve solution for this kind of attack?
We have Spring, Primefaces and Spring Security used in our application. We tried implementing below tags in our Spring security.xml file. However, it doesnt seem to generate new JSESSIONID post authentication is successful with ADFS. This spring-security.xml has been added in web.xml. Can you let us know what is wrong with below use? We are using Spring Security 3.2.10 in project.
<sec:http create-session="always" use-expressions="true">
<sec:intercept-url pattern="/*" />
<sec:http-basic />
<sec:session-management invalid-session-url="/"
session-fixation-protection="newSession">
<sec:concurrency-control max-sessions="150"
expired-url="/" />
</sec:session-management>
<sec:csrf/>
</sec:http>
<sec:authentication-manager alias="authenticationManager">
<sec:authentication-provider>
<sec:user-service>
<sec:user name="abc" password="abc" authorities="ROLE_USER" />
</sec:user-service>
</sec:authentication-provider>
</sec:authentication-manager>

If you are using the Basic authentication for API, you'd better not create new session
<sec:http create-session="stateless" ....
If you want to create new session post authentication, the default Basic Filter is not supported, but you can implement your own filter and just like AbstractAuthenticationProcessingFilter, there is SessionAuthenticationStrategy in it, and SessionFixationProtectionStrategy will create a new session with exist attributes in old session post authentication.

I suposse you are using form-login because talking about users login in. Spring includes out-of-the-box session fixation protection. In SessionManagementFilter, in doFilter method, you can see that if the user has been authenticated in the current request, the session authentication strategy is called. This strategy by default is SessionFixationProtectionStrategy.
Apparently your configuration is correct, debug that method and check what is happening. Besides, login forms are recommended to be light and sessionless if possible, so default create-session value "IfRequired" should be preferred instead of "always". Anyway newSession strategy should invalidate current session, ceate a new one and return a new JSESSIONID cookie.

Related

How to prevent session fixation with a Keycloak Spring Security setup?

We use keycloak as our identity and access provider that is connected with spring security by keycloak's spring security adapter. We realized that the session id does not change when a user logs in the application which is an open door for session fixation attacks. Both keycloak and spring security provide solutions for preventing session fixation but when I use both in combination none of them works properly.
From keycloak's documentation:
turn-off-change-session-id-on-login
The session id is changed by default on a successful login on some platforms to plug a security attack vector. Change this to true if you want to turn this off This is OPTIONAL. The default value is false.
I didn't turn off this feature but the session id still remains the same after login procedure.
Spring security comes along with two implementations of the SessionAuthenticationStrategy, ChangeSessionIdAuthenticationStrategy and SessionFixationProtectionStrategy, but none of them does the trick.
In the keycloak doku you can find a hint that "SessionFixationProtectionStrategy is currently not supported" but there is no advice how to deal with the session fixation risk in this setup. But according to this hint it should still be possible to change the session id with spring security with the consequence that "universal log out will not work" anymore. But even this I don't get to work (maybe we could go with the trade-off and lose the universal logout)
I tried changing the session id with spring security on some ways (extraction of the configuration file):
overwrite default session management filter by following this instructions
<http use-expressions="true" auto-config="false" entry-point-ref="keycloakAuthenticationEntryPoint">
[...]
<!-- changeSessionId and newSession have no result at all -->
<session-management session-fixation-protection="none"/>
<session-management session-authentication-strategy-ref="sessionAuthenticationStrategy"/>
<custom-filter ref="sessionManagementFilter" position="SESSION_MANAGEMENT_FILTER"/>
[...]
</http>
<beans:bean id="sessionAuthenticationStrategy"
class="org.springframework.security.web.authentication.session.ChangeSessionIdAuthenticationStrategy"/>
<beans:bean id="sessionManagementFilter" class="org.springframework.security.web.session.SessionManagementFilter">
<beans:constructor-arg name="securityContextRepository" ref="securityContextRepository"/>
<beans:constructor-arg name="sessionStrategy" ref="sessionAuthenticationStrategy"/>
</beans:bean>
Overwrite default session management filter by this instruction
<http ...>
<session-management session-authentication-strategy-ref="sessionStrategy"/>
</http>
<bean id="sessionStrategy" class="org.springframework.security.web.authentication.session.ChangeSessionIdAuthenticationSessionStrategy"/>
Changing the behaviour of the default session management filter according to spring's documentation
<http use-expressions="true" auto-config="false" entry-point-ref="keycloakAuthenticationEntryPoint">
[...]
<!-- changeSessionId and newSession have no result at all -->
<session-management session-fixation-protection="changeSessionId"/>
[...]
</http>
Any hints are appreciated about preventing session fixation within a keycloak spring security environment.

Share Spring Security Context across multiple http sections

I have a situation where I have the basic application being served on the main endpoint (/**). I use spring security to authenticate the user before serving any further resources. The authentication is done with a login form.
But specifically the endpoint (/lti/**) is being used in a different Http Section. There, Spring security handles the authentication using OAuth.
After authentication on the /lti/** endpoint, the user is expected to load my entire application in an iFrame. This means access to all resources protected by the 1st Http-section.
Now the problem here is even though the user authenticated using OAuth creds for loading the app from /lti/**, and I set all appropriate user roles, when the application loads in the iFrame and tries to access any resources, it redirects to the login screen as directed by the 1st Http-section (The succeeding calls are through AJAX if that helps, but you can see the response in the dev tools).
Based on my research so far, the Security Context is not shared among different entry points. Different firewalls are instantiated so the Security context itself is re-initiated.
Here's a bit of my Security context:
<security:http pattern="/lti/**" use-expressions="true" entry-point-ref="oAuthProcessingFilterEntryPoint">
<security:headers>
<security:frame-options disabled="true"/>
</security:headers>
<security:intercept-url pattern="/**" access="hasRole('ROLE_OAUTH')"/>
<!-- Filter -->
<security:custom-filter ref="oAuthProcessingFilter" before="ANONYMOUS_FILTER"/>
<!-- Disable CSRF -->
<security:csrf disabled="true"/>
</security:http>
<security:http>
<security:intercept-url ... />
....
<security:form-login
authentication-success-handler-ref="authenticationSuccessHandler"
login-page=............"/>
<security:logout ................./>
<security:session-management invalid-session-url="............." session-authentication-error-url="................">
</security:session-management>
<!-- Enable csrf protection -->
<security:csrf/>
</security:http>
Any approach that will work or have any ideas how I ccan tackle the situation?
SecurityContext is populated in every request, the FilterChain set it up at the beginning of the request by using the SecurityContextPersistenceFilter. By deafult, this filter store the authentication data in the HttpSession.
The users are authenticated in a page an then you load an Iframe which starts a different HttpSession (you could check this if you watch the sessionids).
Then you have several options:
Do not use an Iframe. The best option, if it is not a must.
Configure a default RememberMe filter. the problem is that the users will be remembered in each session, until the cookie expires.
Store the SecurityContext in a more persistent way than the session.
Summarizing, I think that your problem is not about different entry points, its about different sessions.

Spring Security custom filter registration with Java config

I am trying to setup pre-authentication authorisation using Spring Security, similar to site minder where an external system does the authentication and saves login information in a cookie. However for that to happen I need to redirect to the external URL.
I tried doing it from an implementation of AbstractPreAuthenticatedProcessingFilter but that doesn't work because the HttpServletResponse object is not available.
A more appropriate way seems to be to just add a custom filter that checks for cookie and does the redirection and once the cookies are available then passes the control forward to Spring Security filter. How can I register this custom filter in a Java configuration based Spring Security application? Any help would be appreciated.
The common way is to redirect user to the external authentication interface using an AuthenticationEntryPoint, for example LoginUrlAuthenticationEntryPoint. The entry point is automatically invoked by Spring Security whenever it determines that user needs to get authenticated.
Once user returns back to your application, it should hit a custom filter which extends the AbstractPreAuthenticatedProcessingFilter and extracts the username from your cookie/header/token (after perhaps some validity and integrity checks) in method getPreAuthenticatedPrincipal.
The Spring configuration could be similar to:
<security:http entry-point-ref="externalAuthentication">
<security:custom-filter after="BASIC_AUTH_FILTER" ref="cookieAuthentication"/>
<security:intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY"/>
</security:http>
<bean id="externalAuthentication" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<constructor-arg value="http://server.local/authenticationService"/>
</bean>
<bean id="cookieAuthentication" class="custom class extending org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter">
...
</bean>

Spring Security in a Stateless webapp? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
create-session stateless usage
Im just beginning experimenting on Spring Security, on version 3.1, and im wondering how to achieve authentication with a stateless webapp.
http-basic and digest come to mind, and i've tried them, but i dislike the inability to logout like the form authentication without closing the browser.
I currently have a working stateless webapp with form-based authentication using spring security (which makes it stateful by storing auth stuffs in session perhaps ?), and i wonder what are the strategies that i could research on to make spring security work without making use of http sessions ?
I realize that there's a <http create-session="stateless" ..>, but there must be something that needs more doing because the app stops working correctly after i tried that, by keep authenticating me when accessing protected resources.
Here's my config :
<http use-expressions="true" create-session="stateless">
<form-login login-page="/login"
login-processing-url="/static/j_spring_security_check"
authentication-failure-url="/login?login_error=t" />
<logout logout-url="/static/j_spring_security_logout"/>
<intercept-url pattern="/person/test/**"
access="isAuthenticated() and principal.username=='albertkam'"
/>
<intercept-url pattern="/person/**" access="hasRole('ROLE_NORMAL')"/>
<remember-me
key="spitterKey"
token-validity-seconds="2419200"/>
</http>
With create-session="stateless" :
accessing http://myhost:8080/mycontext/person/blah
goes to login page
returns to homepage url http://myhost:8080/mycontext after logging in (i expect it returns to the protected resource)
Without create-session="stateless", which defaults to ifRequired (stateful) :
accessing http://myhost:8080/mycontext/person/blah
goes to login page
returns to the protected url http://myhost:8080/mycontext/person/ blah after logging in (this is correct behaviour , but stateful)
You can use always-use-default-target="false" on <form-login>to prevent going to default page after successful login.

Spring Security 3 RestTemplate POST to j_spring_security_check

I am using Spring Security 3 with REST endpoints. I managed to get a basic Spring Security working.
Part of the security-context.xml
<security:http auto-config="true" use-expressions="true" access-denied-page="/rest/denied" >
<security:intercept-url pattern="/rest/*" access="ROLE_USER"/>
and basic config as found on the web
<security:authentication-manager>
<security:authentication-provider user-service-ref="userDetailsService">
<security:password-encoder ref="passwordEncoder"/>
</security:authentication-provider>
<!-- Use a Md5 encoder since the user's passwords are stored as Md5 in the database -->
<bean class="org.springframework.security.authentication.encoding.Md5PasswordEncoder" id="passwordEncoder"/>
<!-- An in-memory list of users. No need to access an external database layer.
See Spring Security 3.1 Reference 5.2.1 In-Memory Authentication -->
<!-- john's password is admin, while jane;s password is user -->
<security:user-service id="userDetailsService">
<security:user name="john" password="21232f297a57a5a743894a0e4a801fc3" authorities="ROLE_USER, ROLE_ADMIN" />
<security:user name="jane" password="ee11cbb19052e40b07aac0ca060c23ee" authorities="ROLE_USER" />
</security:user-service>
I want to login to j_spring_security_check using a RestTemplate POST.
HttpEntity<String> entity = new HttpEntity<String>(request, headers);
HashMap<String, String> map = new HashMap<String, String>();
map.put("j_username", "john");
map.put("j_password","21232f297a57a5a743894a0e4a801fc3");
String response = restTemplate.postForObject("http://localhost:8080/rest/j_spring_security_check", map, String.class);
but in the log, it seems the username parameter is not being read
DEBUG o.s.s.authentication.ProviderManager - Authentication attempt using org.springframework.security.authentication.dao.DaoAuthenticationProvider
DEBUG o.s.s.a.d.DaoAuthenticationProvider - User '' not found
DEBUG o.s.s.w.a.UsernamePasswordAuthenticationFilter - Authentication request failed: org.springframework.security.authentication.BadCredentialsException: Bad credentials
What is the correct way to get the REST Template to post auth credentials? Is there a better way to login in/ get authorized other than j_spring_security_check? Does the information go in the header?
Thanks in advance.
This seems like a duplicate of another SO question. You are probably approaching this the wrong way, though. Typically if you are issuing a REST request you wouldn't be authenticating at the same time - this doesn't make any sense - certainly not using form POST style logic.
For authentication of REST requests you should be using another form of authentication (assuming these requests are generated programmatically):
* HTTP Basic auth
* X.509 certificates
OR if this is happening through an XHR / Javascript origin, you should be prepared to have the request fail and redirect the user to the login mechanism. Typically handling REST style requests with Spring Security is not at all the same as handling regular secured pages. You should be prepared for some amount of complexity.
Good luck!

Resources