How to prevent HTTP session flood attack - spring

Flood Attack:
In short, a hacker can keep hitting the server (without cookie) to force Java container to keep creating new session.
I am using Spring Security to manage session. I realize jsessionid keep being created before login, this is not what I want.
So I did:
1) in Spring security config:
sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER)
2) disable session creation in jsp. Because I am using apache tile, due to it is using dynamic include, so I have to disable session creation in all the jsp fragment. This is very tedious.
<%#page session="false"%>
First glance, it is fine, but there is a scenario I still got the session created.
Let's say before login, I visit a url that only can be visited after authenticated, Spring will redirect me to login page.
Before I am redirected, the response already instruct to set a new cookie, a session already created.
My Question:
1) Is session flood attack a serious issue? Should I really take care of it?
2) Is there any better way to handle this issue? Any best practise?
3) What happen to my code? It should work actually, I suspect the cookie is created by Spring, although I already set it to SessionCreationPolicy.NEVER. I can't set it to Stateless, I still need the session after login.
I am more concerned session attack compare to DDOS actually, I have also set .maximumSessions(1) in Spring to prevent multiple login. But above issue happen before login. Please help. Thanks.

Your point looks valid, it probably can be a serious issue if not handled. I found there is already an open issue on this topic. But there is a work around available to control this behavior.
public class ApiSecurityConfig extends WebSecurityConfigurerAdapter {
public HttpSessionRequestCache getHttpSessionRequestCache() {
HttpSessionRequestCache httpSessionRequestCache = new HttpSessionRequestCache();
httpSessionRequestCache.setCreateSessionAllowed(false);
return httpSessionRequestCache;
}
#Override
protected void configure(final HttpSecurity http) throws Exception {
http.requestCache().requestCache(getHttpSessionRequestCache());
}
Refer following links for more details.
https://github.com/spring-projects/spring-security/issues/4242
How to stop Spring Security from creating a new session?

Related

Why the session attribute is coming as null

A HTML5 UI is connected to the backend (REST Jersey to business logic to Hibernate and DB). I need to create and maintain a session for each user login until the user logs out.
I am clueless on how to approach this problem.
I followed this approach
Initially when the User is successfully logs in , i am setting attribute under session as shown below
HttpSession session = request.getSession(true);
session.setAttribute("islogged", "islogged");
String value = (String)session.getAttribute("islogged");
System.out.println("****************** The User Logge in Value"+value);
Later in a different page i am checking if the user is logged in or not this way
public String checkIfUserLoggedIn() throws JSONException,ClassNotFoundException, SQLException
{
HttpSession session = request.getSession();
String value = (String)session.getAttribute("islogged");
if(value==null)
{
// always its coming here only
}
}
I agree with francesco foresti, please do not rely on HTTP session without Auth. this is unsafe, and quite dangerous for your app.
Have you been implementing a specific session mecanism ?
If not, jersey as it is will not store session data as it. Every call that you will make will give you a session id that is different from yours.
You have to make authentication & use the auth token in order to identify you session.
use JAX-RS
Please do use an auth mecanism as defined : https://jersey.java.net/documentation/latest/security.html
#Path("authentication")
#Singleton
public static class MyResource {
// Jersey will inject proxy of Security Context
#Context
SecurityContext securityContext;
#GET
public String getUserPrincipal() {
return securityContext.getUserPrincipal().getName();
}
}
or use another framework : Spring, Shiro.... etc.
I really prefer that solution, since another framework will implement a lot of stuff for you. You gain a lot of time doing so.
Please take a look to official jersey doc: https://jersey.java.net/documentation/latest/index.html
I wouldn't rely on the http session. My approach would be to put an "Authorization" field in the header of the response that the server returns when the user logs in, and ask the user to put the very same header in each suqsequent call. In this header you put the informations that help the server find the identity of the user
(take a look at what twitter does as an example : https://dev.twitter.com/oauth/overview/authorizing-requests). The server could save the informations about the logged in user in the database, or You could create a Map in a Singleton that would serve as the "authorization gatekeeper" for your services.

CSRF token expires during login

I'm working on Spring web application and I need to avoid problem with expire csrf token on login page, because if user is waiting too long and try to login only one way to resolve problem with csrf is to reload page and try to login again. But it's not user friendly and I want to avoid this situation.
First question: Is it possible in general(by spring security 3.2.4)? Without disable csrf.
I tried to use security="none" for login page and spring seciruty "login_check", but it's not working, i got infinity redirect or I got error that no mapping for url "myhost/login_check".
Second question: How can i do it?
Recommended solution
I would say that you should not disable csrf tokens on a production site. You may make session (and thus the csrf token) last longer (but it usually should not last longer than a day, especially for not-logged-in users as it is a DOS vector), but the real solution may be to automatically refresh the login page when the csrf token expires. You may use a
<META HTTP-EQUIV="REFRESH" CONTENT="csrf_timeout_in_seconds">
in your login page header. If the user lets the login page sit for hours, it should not bother him that the page got refreshed.
Second solution
A possible solution which does not require you to actually store sessions but allows for infinite timeout is that you can generate your csrf tokens with hashing from the session id and a server-side secret:
csrf = hash(sessionid+secret)
Note however that you need to really dig and override spring-security internal mechanisms, namely:
re-creating anonymous sessions on the fly if a request arrives and no such session exists
re-creating the csrf token on the fly from the session id
And choose a very secure hashing algorithm, preferably sha-512.
Third solution
You could have a small javascript that calls a no-op page on your server regularly (just before the session timeout), thus extending your session. This results in infinite session timeout only if the browser is on all the time, so the DOS aspect is mitigated.
Ok, one last solution
You can alter the CSRF token checking code, and disable it for the login page. This is actually synonymous with the second solution, but is specific for the login page, not generally for all anonymous sessions.
You can do this e.g. by setting a custom RequestMatcher in HttpSecurity:
http.csrf().requireCsrfProtectionMatcher(new MyCsrfRequestMatcher());
...
class MyCsrfRequestMatcher implements RequestMatcher {
#Override
public boolean matches(HttpServletRequest request) {
return !request.getServletPath().equals("/login");
}
}
Another option would be set no timeout for the session by default and then, when the user is authenticated, change the timeout to whatever you want. You can see an example of how to do this here.
In one of the projects I worked on, I implemented the following:
Implement an exception handler which handles CsrfException (or AccessDeniedException in general in my case). Forward the request to a controller method.
#ExceptionHandler(AccessDeniedException.class)
#ResponseStatus(value = HttpStatus.FORBIDDEN)
public void handleAccessDeniedException(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
request.setAttribute(WebAttributes.ACCESS_DENIED_403, accessDeniedException);
request.getRequestDispatcher("/Access_Denied").forward(request, response);
}
In the controller method, check whether the original request is for the login page. If so, show an appropriate message within the login page.
if ("/login".equals(request.getAttribute(RequestDispatcher.FORWARD_SERVLET_PATH))) {
model.addAttribute("error", "An invalid security token has been detected. Please try again.");
return "login.jsp";
} else {
return "accessDenied.jsp";
}
With this approach, user will be able to retry the login without the need to refresh.
You can also make your CSRF protection rely on cookies and NOT server side session state. Spring Security has full support for this.
CookieCsrfTokenRepository
You will only receive a timeout if your cookie expires. This scales well since it's basically stateless (from the server's perspective).
#EnableWebSecurity
public class WebSecurityConfig extends
WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
}
}
Andrew

How do I change session timeout for a single page under Tomcat running a Spring security controlled application?

Part of my application has a single page view for an overhead status board. Access to the server that runs the overhead display is in an access controlled location that only a few key people have access to. The problem I am encountering is that the session expires after a set amount of time, necessitating someone physically going to the server and reloading the page. Needless to say this creates some problems when the key people aren't around.
This application runs under Tomcat, and security is controlled via Spring security. How would I go about changing the session timeout for this page only?
[edit]
I've taken the approach that #sotirios-delimanolis suggested. Although I still need to find an elegant way to reverse the extended session timeout if the user navigates to this page then navigates away, this appears to work for me.
Following is the relevant snippet of code that implements this:
#RequestMapping(value="BigBoard", method = RequestMethod.GET)
public void getBigBoard(HttpServletRequest request, Model model) {
HttpSession session = request.getSession();
session.setMaxInactiveInterval(604800);
I don't know how your page is accessed, by controller, resource provider, etc. but you would have to add a Servlet, Filter, HandlerInterceptor or handler method somewhere in the processing of that request that basically did the following
int seconds = ...; // timeout
request.getSession(true).setMaxInactiveInterval(seconds);
That session now has the specified timeout before the container invalidates it.
Note that if the user goes to some other page somehow, the timeout for their session will remain what you set above unless you change it.
Make the page refresh itself every now and then (using <meta http-equiv="refresh" content="60">) or add some Ajax polling to avoid session timeout.

How to pass / copy the parameter in java springs 2.5.6 when we switch between https to http

In my code I am using spring direct login.
Once controller switches between https to http a new session is created, once new session is created, how do I pass/ copy the session attribute to new session Which was created by http?
Check the Spring Security FAQ. Basically, you can't copy the session attributes - all the session data from the previous is lost when you switch back to HTTP. Since the browser won't send the secure cookie, you have a new session and it's as if you hadn't logged in at all.
There are ways of working around this (see the FAQ for more details and search the web) but they are generally a bad idea. You should start in HTTPS and stay that way if security is important.

Spring HTTP Invoker session (state) storage

i have a Swing-client and a Server running on tomcat 7, which communicate with each other using Spring (3.1) HTTP invoker. The communication works fine so far (even with TSL), but now i am trying to add Spring Security.
side-note: In a typical webapplication i would use basic authentication to authenticate the user. After my CustomAuthenticationProvider returns an Authentication object for the user, everything "just works", meaning that on every further request the SecurityContext is automatically set. I guess the login returns a session-key to the client which is send on every request to identify the session.
That is pretty much what i am looking for with HTTP-Invoker. At the moment it seems like i get a new context on every request, which is bad, because my customAuthenticationManager.authenticate(Authentication auth) method is pretty costy and should really only be called once per user-session.
Any Idea?
edit i found some hints on this at http://forum.springsource.org/showthread.php?10764-Maintaing-State-while-using-HttpInvoker ,but as this link is more then 8 years old, i was hoping for an easier solution.
I found the solution now. First you need to know that the spring-security part is completely the same as it would be in a webapplication (which is great).
On client-side you need a more complex HTTP-client implementation. I used org.springframework.remoting.httpinvoker.HttpComponentsHttpInvokerRequestExecutor. On server-side you could use the create-session="always"-Attribute of the <http-element to ensure that a session is always created. However, i found it better to create the session myself (just call httpServletRequest.getSession() which creates a session if non exists), because that way you can specify when to do that. In my case i create the session in my authenticationProvider only if authentication was successful.

Resources