The attack scenario with this vulnerability is that a user can open a browser on a shared terminal and record the session identifier set by the application. Later when any other user of the system logs into the application without closing instances of that browser the same cookie will be used to track the victim's session.
Alternatively, if the application is susceptible to cross-site scripting on a publicly accessible page (most damagingly the home page), an attacker can use this vulnerability to learn the value of the session identifier, because the cookie does not change since it was first set. The attacker now knows the value of the session token can hijack the victim's session. This is a limited session fixation attack where the attacker does not have control over the value of the session identifier, but is able to know its value through various means before and after a user authenticates.
Most times, invalidating the session and creating a new one may suffice. However, if you are storing variables or objects, you may need to carry these variables or objects from the old session into the new session.
Below is a javax.servlet.Filter. This filter protects against the Session Fixation attacks described above. The filter looks for a specific session attribute, the (NEW_SESSION_INDICATOR) attribute. If one is found, the filter copies out relevant session data to a map, invalidates the session, creates a new session and loads the new session with the old session data.
The filter is simply mapped in your web.xml. Any place you successfully authenticate, an attribute is added to the session (NEW_SESSION_INDICATOR).
The code below follows:
import java.io.IOException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
public class NewSessionFilter implements Filter {
private static Logger logger = Logger.getLogger(NewSessionFilter.class.getName());
public static final String NEW_SESSION_INDICATOR = "filter.NewSessionFilter";
public void destroy() {}
@SuppressWarnings("unchecked")
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
if (request instanceof HttpServletRequest){
HttpServletRequest httpRequest = (HttpServletRequest) request;
if (httpRequest.getSession(false) != null &&
httpRequest.getSession(false).getAttribute(NEW_SESSION_INDICATOR) != null
){
//copy session attributes from new session to a map.
HttpSession session = httpRequest.getSession();
HashMap old = new HashMap();
Enumeration keys = (Enumeration) session.getAttributeNames();
while (keys.hasMoreElements()) {
String key = keys.nextElement();
if (!NEW_SESSION_INDICATOR.equals(key)) {
old.put(key, session.getAttribute(key));
session.removeAttribute(key);
}
}
logger.info("session invalidated on " + httpRequest.getRequestURI());
//invalidation session and create new session.
session.invalidate();
session = httpRequest.getSession(true);
//copy key value pairs from map to new session.
for (Map.Entry entry : old.entrySet()) {
session.setAttribute(entry.getKey(), entry.getValue());
}
logger.info((new StringBuffer()).append("new Session for URI '")
.append(httpRequest.getRequestURI()).append("':")
.append( session.getId()).toString());
}
}
chain.doFilter(request, response);
}
public void init(FilterConfig filterconfig) {}
}
Any questions about this posting or filter, comment below and I'll be sure to answer.