Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>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</p> <pre><code>String sslId = (String) req.getAttribute("javax.servlet.request.ssl_session"); </code></pre> <p>(Note that the attribute key may change in the future to <code>javax.servlet.request.ssl_session</code><strong><code>_id</code></strong> - as part of the Servlet 3.0 spec).</p> <p>I set up a servlet with the following <code>doGet</code> method:</p> <pre><code>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&lt;String, Object&gt; 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&lt;String, Object&gt;) session.getAttribute("protected"); if (secrets == null) { secrets = new HashMap&lt;String, Object&gt;(); 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(); } </code></pre> <p>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</p> <pre><code>http://localhost:8080/EchoWeb/unprotected </code></pre> <p>(my web.xml, like yours, only protects /user/* and /personal/*):</p> <pre> URI: /EchoWeb/unprotected SID: 9ACCD06B69CA365EFD8C10816ADD8D71 SSLID: null Info: unprotected: 1254034761932 Secret: null Date: 27/09/09 07:59 </pre> <p>Next, I tried to access a protected URL</p> <pre><code>http://localhost:8080/EchoWeb/personal/protected </code></pre> <p>and, as expected, I got redirected to</p> <pre><code>https://localhost:8443/EchoWeb/personal/protected </code></pre> <p>and the response was</p> <pre> URI: /EchoWeb/personal/protected SID: 9ACCD06B69CA365EFD8C10816ADD8D71 SSLID: 4abf0d67549489648e7a3cd9292b671ddb9dd844b9dba682ab3f381b462d1ad1 Info: unprotected: 1254034761932 Secret: protected: 1254034791333 Date: 27/09/09 07:59 </pre> <p>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.</p> <p>I set up a Python script, <code>spoof.py</code>:</p> <pre><code>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() </code></pre> <p>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:</p> <pre> 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 </pre> <p>Notice in the above responses that the session data (a value with a timestamp of <code>1254034761932</code>) 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 <strong>not secure</strong>. However, note that the SSL IDs <strong>were different each time</strong> and if you use <em>those</em> to key into your session data (e.g. as shown), you should be safe. If I refresh my Firefox tab, here's the response:</p> <pre> URI: /EchoWeb/personal/protected SID: 9ACCD06B69CA365EFD8C10816ADD8D71 SSLID: 4abf0d67549489648e7a3cd9292b671ddb9dd844b9dba682ab3f381b462d1ad1 Info: unprotected: 1254034761932 Secret: protected: 1254034791333 Date: 27/09/09 08:05 </pre> <p>Notice that the SSLID is <strong>the same</strong> 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 <em>different</em> for each of the spoofed sessions and also different from the Firefox session.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload