Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to prevent tomcat session hijacking?

Tags:

java

tomcat

In my web.xml I've defined a user-data-constraint for some resources:

<security-constraint>
    <web-resource-collection>
        <web-resource-name>Personal Area</web-resource-name>
        <url-pattern>/personal/*</url-pattern>
    </web-resource-collection>
    <web-resource-collection>
        <web-resource-name>User Area</web-resource-name>
        <url-pattern>/user/*</url-pattern>
    </web-resource-collection>
    <user-data-constraint>
        <transport-guarantee>CONFIDENTIAL</transport-guarantee>
    </user-data-constraint>
</security-constraint>
  1. When I load the page with http I've got my JSESSIONID ID1 in my cookie.
  2. When I change to context/user/sample.faces then Tomcat makes a 302 redirect to HTTPS. But my JSESSIONID is still ID1.

I think this is a vulnerability? Or is it my configuration mistake?

The problem I see is the following: While browsing over HTTP with cookie ID1 there is an attacker who is listening to my network traffic. He "steals" my cookie ID1. Now I switch to HTTPS and my cookie is still ID1. I login. The attacker is then able to taker over my session because he knows my cookie...

like image 592
Marcel Avatar asked Sep 14 '09 17:09

Marcel


People also ask

How can session hijacking be prevented?

There are several ways to prevent session hijacking from happening: Use strong passwords and multifactor authentication. These techniques protect accounts from being accessed by hackers if they manage to steal a user's session ID (Alkove, 2021). Only share session IDs with trusted sources.

What is the best defense against session hijacking?

The best defense against session hijacking is to force secure, encrypted communications over TLS/SSL. This is also sometimes called "HTTPS". Cookies will still be sent with every request but their contents will not be visible because the entire communication will be encrypted while in transit.

How do I make my session ID secure?

The session ID is generated using the Random Number Generator (RNG) cryptographic provider. The service provider returns a sequence of 15 randomly generated numbers (15 bytes x 8 bit = 120 bits). The array of random numbers is then mapped to valid URL characters and returned as a string.

Does VPN prevent session hijacking?

There are several things you can do to prevent session hijacking and protect your data and identity online, including: Use a VPN. A high-quality VPN can mask your IP address and keep your online activity private and secure. Avoid public or unsecure Wi-Fi networks.


1 Answers

If it's a recent version of Tomcat, you may not have a problem. However, this depends on your checking the SSL ID associated with the session. This is available using code such as

String sslId = (String) req.getAttribute("javax.servlet.request.ssl_session");

(Note that the attribute key may change in the future to javax.servlet.request.ssl_session_id - as part of the Servlet 3.0 spec).

I set up a servlet with the following doGet method:

protected void doGet(HttpServletRequest request, HttpServletResponse response)
                    throws ServletException, IOException {
    HttpSession session = request.getSession(true);
    String sid = session.getId();
    String sslId = (String) request.getAttribute(
                "javax.servlet.request.ssl_session");
    String uri = request.getRequestURI();
    OutputStream out = response.getOutputStream();
    PrintWriter pw = new PrintWriter(out);
    HashMap<String, Object> secrets;
    Object secret = null;
    Object notSecret;
    Date d = new Date();

    notSecret = session.getAttribute("unprotected");
    if (notSecret == null) {
        notSecret = "unprotected: " + d.getTime();
        session.setAttribute("unprotected", notSecret);
    }
    secrets = (HashMap<String, Object>) session.getAttribute("protected");
    if (secrets == null) {
        secrets = new HashMap<String, Object>();
        session.setAttribute("protected", secrets);
    }
    if (sslId != null) {
        if (secrets.containsKey(sslId))
            secret = secrets.get(sslId);
        else {
            secret = "protected: " + d.getTime();
            secrets.put(sslId, secret);
        }
    }
    response.setContentType("text/plain");
    pw.println(MessageFormat.format("URI: {0}", new Object[] { uri }));
    pw.println(MessageFormat.format("SID: {0}", new Object[] { sid }));
    pw.println(MessageFormat.format("SSLID: {0}", new Object[] { sslId }));
    pw.println(MessageFormat.format("Info: {0}", new Object[] { notSecret }));
    pw.println(MessageFormat.format("Secret: {0}", new Object[] { secret }));
    pw.println(MessageFormat.format("Date: {0}", new Object[] { d }));
    pw.close();
}

I then invoked a suitable unprotected URL using Firefox and the Live HTTP Headers extension, to get the session cookie. This was the response sent when I navigated to

http://localhost:8080/EchoWeb/unprotected

(my web.xml, like yours, only protects /user/* and /personal/*):

URI: /EchoWeb/unprotected
SID: 9ACCD06B69CA365EFD8C10816ADD8D71
SSLID: null
Info: unprotected: 1254034761932
Secret: null
Date: 27/09/09 07:59

Next, I tried to access a protected URL

http://localhost:8080/EchoWeb/personal/protected

and, as expected, I got redirected to

https://localhost:8443/EchoWeb/personal/protected

and the response was

URI: /EchoWeb/personal/protected
SID: 9ACCD06B69CA365EFD8C10816ADD8D71
SSLID: 4abf0d67549489648e7a3cd9292b671ddb9dd844b9dba682ab3f381b462d1ad1
Info: unprotected: 1254034761932
Secret: protected: 1254034791333
Date: 27/09/09 07:59

Notice that the cookie/session ID is the same, but we now have a new SSLID. Now, let's try to spoof the server using the session cookie.

I set up a Python script, spoof.py:

import urllib2

url = "https://localhost:8443/EchoWeb/personal/protected"
headers = {
    'Host': 'localhost:8080',
    'User-Agent': 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-GB; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3',
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
    'Accept-Language': 'en-gb,en;q=0.5',
    'Accept-Charset': 'ISO-8859-1,utf-8;q=0.7,*;q=0.7',
    'Cookie' : 'JSESSIONID=9ACCD06B69CA365EFD8C10816ADD8D71'
}
req = urllib2.Request(url, None, headers)
response = urllib2.urlopen(req)
print response.read()

Now, you don't need to know Python, particularly - I'm just trying to send an HTTP request to a (different) protected resource with the same session ID in the Cookie. Here's the response when I ran my spoof script twice:

C:\temp>spoof
URI: /EchoWeb/personal/protected
SID: 9ACCD06B69CA365EFD8C10816ADD8D71
SSLID: 4abf0eafb4ffa30b6579cf189c402a8411294201e2df94b33a48ae7484f22854
Info: unprotected: 1254034761932
Secret: protected: 1254035119303
Date: 27/09/09 08:05


C:\temp>spoof
URI: /EchoWeb/personal/protected
SID: 9ACCD06B69CA365EFD8C10816ADD8D71
SSLID: 4abf0eb184cb380ce69cce28beb01665724c016903650539d095c671d98f1de3
Info: unprotected: 1254034761932
Secret: protected: 1254035122004
Date: 27/09/09 08:05

Notice in the above responses that the session data (a value with a timestamp of 1254034761932) which was set in the first, unprotected request, has been sent throughout, because Tomcat is using the same session because the session ID is the same. This is of course not secure. However, note that the SSL IDs were different each time and if you use those to key into your session data (e.g. as shown), you should be safe. If I refresh my Firefox tab, here's the response:

URI: /EchoWeb/personal/protected
SID: 9ACCD06B69CA365EFD8C10816ADD8D71
SSLID: 4abf0d67549489648e7a3cd9292b671ddb9dd844b9dba682ab3f381b462d1ad1
Info: unprotected: 1254034761932
Secret: protected: 1254034791333
Date: 27/09/09 08:05

Notice that the SSLID is the same as for the earlier Firefox request. So, the server can tell the sessions apart using the SSL ID value. Notice particularly that the "protected data" is the same for each request made from the Firefox session, but different for each of the spoofed sessions and also different from the Firefox session.

like image 190
Vinay Sajip Avatar answered Oct 07 '22 16:10

Vinay Sajip