In session fixation attack, a hacker obtains/sets (by any means) another person's session id. The hacker then can impersonate as the other person and can get the sensitive information.
Java Servlet 3.1 introduced following method of HttpServletRequest:
String changeSessionId()
This method changes the current session id with a new one, hence providing the protection against session fixation attack.
Servlet 3.1 also introduced HttpSessionIdListener for receiving HttpSession id change notification.
For versions prior to 3.1, we can use following steps:
HttpSession session = .....
.....
session.invalidate();
session=request.getSession(true);
//now set data from old session here
Example
In following example, we will learn how to use Servlet 3.1 API against session fixation.
A Login servlet
@WebServlet(name = "userLoginServlet", urlPatterns = {"/login"})
public class LogInServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
HttpSession session = req.getSession();
String userKey = "loggedInUser";
User user = (User) session.getAttribute(userKey);
if (user == null) {
user = loadUserForRequest(req);
session.setAttribute(userKey, user);
}
prepareLogginInfoHtml(user, resp);
req.changeSessionId();
}
private void prepareLogginInfoHtml(User user, HttpServletResponse resp)
throws IOException {
resp.setContentType("text/html");
PrintWriter w = resp.getWriter();
w.write("User logged in " + user.getName());
w.write("<br/><a href='/balance'>Show Balance</a>");
}
private User loadUserForRequest(HttpServletRequest req) {
//returning a dummy user
return new User("1", "Mike", "12312",
BigDecimal.valueOf(200000));
}
}
public class User {
private String id;
private String name;
private String accountNumber;
BigDecimal currentBalance;
.............
}
Another servlet for some post Login processing
@WebServlet(name = "userBalanceServlet", urlPatterns = {"/balance"})
public class BalanceServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
HttpSession session = req.getSession();
User user = (User) session.getAttribute("loggedInUser");
if (user == null) {
RequestDispatcher dispatcher = getServletContext().getRequestDispatcher("/login");
dispatcher.forward(req, resp);
} else {
prepareBalanceInfoHtml(user, resp);
req.changeSessionId();
}
}
private void prepareBalanceInfoHtml(User user, HttpServletResponse resp) throws IOException {
resp.setContentType("text/html");
PrintWriter w = resp.getWriter();
w.write("User logged in " + user.getName());
w.write("<br/>Balance: " + user.getCurrentBalance());
}
}
Implementing AppSessionIdListener
@WebListener
public class AppSessionIdListener implements HttpSessionIdListener {
@Override
public void sessionIdChanged(HttpSessionEvent event, String oldSessionId) {
System.out.println("oldSessionId: " + oldSessionId);
System.out.println("newSessionId: " + event.getSession().getId());
}
}
To try examples, run embedded Jetty (configured in pom.xml of example project below):
mvn jetty:run
In this tutorial, we are using Jetty plugin instead of tomcat7-maven-plugin because tomcat plugin does not support Servlet 3.1 (it supports version up to 3.0).
Output
On clicking 'Show Balance' link:
Server output
As printed by our HttpSessionIdListener:
.....
oldSessionId: node0md9ox8wtj0e91lr5kpuzw7dql0
newSessionId: node01jl2v0v5bvfwgxvhr7ao2f52z1
....
oldSessionId: node0nyhkl2ej1ret1716bwjwyl9a92
newSessionId: node0mqnz9mrwfg8a1it5hxc7rdg3v3
....
Chrome Inspection - Network Tab
Example ProjectDependencies and Technologies Used: - javax.servlet-api 3.1.0 Java Servlet API
- jetty-maven-plugin 9.4.1.v20170120: Jetty maven plugins.
- JDK 1.8
- Maven 3.3.9
|