Session Fixation is a security vulnerability in web sites. The scenario is this:
- The attacker creates a link to SomeOnlineBank.com in which the URL contains a session ID.
- The user follows the link and the web site platform uses the session ID.
- The user logs on, making that session authenticated.
- The attacker uses the session ID to impersonate the user and steal all of their money.
I was able to reproduce the attack, and mitigate it by changing settings in web.xml. If you use the standard
@WebServlet("/SessionTestServlet") public class SessionTestServlet extends HttpServlet { private static final long serialVersionUID = 1L; @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/plain"); PrintWriter writer = response.getWriter(); writer.println("Requested Session Id: " + request.getRequestedSessionId()); writer.println("Session Id valid: " + request.isRequestedSessionIdValid()); writer.println("Session from parameter: " + request.isRequestedSessionIdFromURL()); writer.println("Session from cookie: " + request.isRequestedSessionIdFromCookie()); HttpSession session = request.getSession(); writer.println("Actual session ID: " + session.getId()); writer.println("Session is new: " + session.isNew()); } }
If I run this servlet and try to inject a Session ID I see the following (requesting http://localhost:8080/TestApp/SessionTestServlet;jsessionid=1234567)
Requested Session Id: 1234567 Session Id valid: false Session from parameter: true Session from cookie: false Actual session ID: 4D041A13FEBC9CD90523BAAB2B5C1B08 Session is new: true
The resulting session is placed into a cookie, and reused for subsequent attempts.
If I change browser and try the URL http://localhost:8080/TestApp/SessionTestServlet;jsessionid=4D041A13FEBC9CD90523BAAB2B5C1B08
I see
Requested Session Id: 4D041A13FEBC9CD90523BAAB2B5C1B08 Session Id valid: true Session from parameter: true Session from cookie: false Actual session ID: 4D041A13FEBC9CD90523BAAB2B5C1B08 Session is new: false
Two browsers are sharing the same Session. I have successfully fixated the session – at least until something happens to change it.
The attack seems limited in a way. I have to make sure my source session is still alive when my victim clicks on the link. This can be done using simple javascript. The same javascript running on my machine could inform me that the victim has logged on and automate the next stage of the attack.
The response from the above request did not set a cookie. If the web site does not allow the servlet container to perform URL rewriting then the stolen Session may be lost.
Mitigation
Try turning off URL Rewriting
Setting the tracking mode to COOKIE only in web.xml seems sufficient. Now it ignores any attempt to pass jsessionid through the matrix parameter. I’ve also set the cookie to “HTTP Only” to prevent access from malicious scripts. I could set “Secure” if I was using HTTPS and did not want my session to be access from a non-HTTPS page. Setting “Secure” prevents sessions being created on non-HTTPS pages.
<session-config> <tracking-mode>COOKIE</tracking-mode> <cookie-config> <http-only>true</http-only> </cookie-config> </session-config>
Verify the client IP address
It is possible to track the client IP address and verify it for future requests. This is not foolproof. For example Network Address Translation or a shared internet proxy would fool it.
Invalidate the Session on logon
Tomcat7 will automatically change the Session ID when Container Security is used to logon. The application I work with implements its own logon management, so has to take its own precautions. It also uses Java CDI so this may be a little harder.
If I invalidate and recreate the Session then I notice that the ID changes every time.
HttpSession session = request.getSession(); session.invalidate(); session = request.getSession();
I’ve not tested this in a CDI environment.