You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2014/06/16 11:52:49 UTC

svn commit: r1602831 - in /tomcat/trunk: test/util/ test/util/TestCookieFilter.java webapps/docs/changelog.xml webapps/examples/WEB-INF/classes/RequestHeaderExample.java webapps/examples/WEB-INF/classes/util/CookieFilter.java

Author: markt
Date: Mon Jun 16 09:52:49 2014
New Revision: 1602831

URL: http://svn.apache.org/r1602831
Log:
Attempt to obfuscate session cookie values associated with other web applications when viewing HTTP request headers with the Request Header example from the examples web application. This reduces the opportunity to use this example for malicious purposes should the advice to remove the examples web application from security sensitive systems be ignored.

Added:
    tomcat/trunk/test/util/
    tomcat/trunk/test/util/TestCookieFilter.java   (with props)
    tomcat/trunk/webapps/examples/WEB-INF/classes/util/CookieFilter.java   (with props)
Modified:
    tomcat/trunk/webapps/docs/changelog.xml
    tomcat/trunk/webapps/examples/WEB-INF/classes/RequestHeaderExample.java

Added: tomcat/trunk/test/util/TestCookieFilter.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/test/util/TestCookieFilter.java?rev=1602831&view=auto
==============================================================================
--- tomcat/trunk/test/util/TestCookieFilter.java (added)
+++ tomcat/trunk/test/util/TestCookieFilter.java Mon Jun 16 09:52:49 2014
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package util;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import org.apache.catalina.authenticator.Constants;
+
+public class TestCookieFilter {
+
+    @Test
+    public void test01() {
+        // Single cookie
+        Assert.assertEquals("a=b", CookieFilter.filter("a=b", null));
+    }
+
+    @Test
+    public void test02() {
+        // Two cookies
+        Assert.assertEquals("a=b;c=d", CookieFilter.filter("a=b;c=d", null));
+    }
+
+    @Test
+    public void test03() {
+        // Cookies with leading and trailing whitespace
+        Assert.assertEquals(" a=b  ;   c=d    ",
+                CookieFilter.filter(" a=b  ;   c=d    ", null));
+    }
+
+    @Test
+    public void test04() {
+        // Empty name (not necessarily valid but checking edge cases in filter)
+        Assert.assertEquals("=b", CookieFilter.filter("=b", null));
+    }
+
+    @Test
+    public void test05() {
+        // Empty value (not necessarily valid but checking edge cases in filter)
+        Assert.assertEquals("a=", CookieFilter.filter("a=", null));
+    }
+
+    @Test
+    public void test06() {
+        // Simple case
+        Assert.assertEquals("JSESSIONID=[obfuscated]",
+                CookieFilter.filter("JSESSIONID=0123456789", null));
+    }
+
+    @Test
+    public void test07() {
+        // Simple SSO case
+        Assert.assertEquals(Constants.SINGLE_SIGN_ON_COOKIE + "=[obfuscated]",
+                CookieFilter.filter(Constants.SINGLE_SIGN_ON_COOKIE + "=0123456789", null));
+    }
+
+
+    @Test
+    public void test08() {
+        // Simple case
+        String id = "0123456789";
+        String cookie = "JSESSIONID=" + id;
+        Assert.assertEquals(cookie, CookieFilter.filter(cookie, id));
+    }
+
+    @Test
+    public void test09() {
+        // Simple SSO case
+        String id = "0123456789";
+        String cookie = Constants.SINGLE_SIGN_ON_COOKIE + "=" + id;
+        Assert.assertEquals(cookie, CookieFilter.filter(cookie, id));
+    }
+
+    @Test
+    public void test10() {
+        // Single cookie
+        Assert.assertEquals("a=\"xx;x\"", CookieFilter.filter("a=\"xx;x\"", null));
+    }
+}

Propchange: tomcat/trunk/test/util/TestCookieFilter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: tomcat/trunk/webapps/docs/changelog.xml
URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/changelog.xml?rev=1602831&r1=1602830&r2=1602831&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/trunk/webapps/docs/changelog.xml Mon Jun 16 09:52:49 2014
@@ -265,6 +265,14 @@
         remove the examples web application from security sensitive systems be
         ignored. (markt/kkolinko)
       </fix>
+      <fix>
+        Attempt to obfuscate session cookie values associated with other web
+        applications when viewing HTTP request headers with the Request Header
+        example from the examples web application. This reduces the opportunity
+        to use this example for malicious purposes should the advice to remove
+        the examples web application from security sensitive systems be ignored.
+        (markt)
+      </fix>
     </changelog>
   </subsection>
   <subsection name="Other">

Modified: tomcat/trunk/webapps/examples/WEB-INF/classes/RequestHeaderExample.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/examples/WEB-INF/classes/RequestHeaderExample.java?rev=1602831&r1=1602830&r2=1602831&view=diff
==============================================================================
--- tomcat/trunk/webapps/examples/WEB-INF/classes/RequestHeaderExample.java (original)
+++ tomcat/trunk/webapps/examples/WEB-INF/classes/RequestHeaderExample.java Mon Jun 16 09:52:49 2014
@@ -18,13 +18,16 @@
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.util.Enumeration;
+import java.util.Locale;
 import java.util.ResourceBundle;
 
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
 
+import util.CookieFilter;
 import util.HTMLFilter;
 
 /**
@@ -79,7 +82,16 @@ public class RequestHeaderExample extend
             out.println("<tr><td bgcolor=\"#CCCCCC\">");
             out.println(HTMLFilter.filter(headerName));
             out.println("</td><td>");
-            out.println(HTMLFilter.filter(headerValue));
+            if (headerName.toLowerCase(Locale.ENGLISH).contains("cookie")) {
+                HttpSession session = request.getSession(false);
+                String sessionId = null;
+                if (session != null) {
+                    sessionId = session.getId();
+                }
+                out.println(HTMLFilter.filter(CookieFilter.filter(headerValue, sessionId)));
+            } else {
+                out.println(HTMLFilter.filter(headerValue));
+            }
             out.println("</td></tr>");
         }
         out.println("</table>");

Added: tomcat/trunk/webapps/examples/WEB-INF/classes/util/CookieFilter.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/examples/WEB-INF/classes/util/CookieFilter.java?rev=1602831&view=auto
==============================================================================
--- tomcat/trunk/webapps/examples/WEB-INF/classes/util/CookieFilter.java (added)
+++ tomcat/trunk/webapps/examples/WEB-INF/classes/util/CookieFilter.java Mon Jun 16 09:52:49 2014
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package util;
+
+import java.util.Locale;
+import java.util.StringTokenizer;
+
+/**
+ * Processes a cookie header and attempts to obfuscate any cookie values that
+ * represent session IDs from other web applications. Since session cookie names
+ * are configurable, as are session ID lengths, this filter is not expected to
+ * be 100% effective.
+ *
+ * It is required that the examples web application is removed in security
+ * conscious environments as documented in the Security How-To. This filter is
+ * intended to reduce the impact of failing to follow that advice. A failure by
+ * this filter to obfuscate a session ID or similar value is not a security
+ * vulnerability. In such instances the vulnerability is the failure to remove
+ * the examples web application.
+ */
+public class CookieFilter {
+
+    private static final String OBFUSCATED = "[obfuscated]";
+
+    private CookieFilter() {
+        // Hide default constructor
+    }
+
+    public static String filter(String input, String sessionId) {
+
+        StringBuilder sb = new StringBuilder(input.length());
+
+        // Cookie name value pairs are ';' separated.
+        // Session IDs don't use ; in the value so don't worry about quoted
+        // values that contain ;
+        StringTokenizer st = new StringTokenizer(input, ";");
+
+        boolean first = true;
+        while (st.hasMoreTokens()) {
+            if (first) {
+                first = false;
+            } else {
+                sb.append(';');
+            }
+            sb.append(filterNameValuePair(st.nextToken(), sessionId));
+        }
+
+
+        return sb.toString();
+    }
+
+    private static String filterNameValuePair(String input, String sessionId) {
+        int i = input.indexOf('=');
+        if (i == -1) {
+            return input;
+        }
+        String name = input.substring(0, i);
+        String value = input.substring(i + 1, input.length());
+
+        if (name.toLowerCase(Locale.ENGLISH).contains("jsessionid") &&
+                (sessionId == null || !value.contains(sessionId))) {
+            value = OBFUSCATED;
+        }
+
+        return name + "=" + value;
+    }
+}

Propchange: tomcat/trunk/webapps/examples/WEB-INF/classes/util/CookieFilter.java
------------------------------------------------------------------------------
    svn:eol-style = native



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org