CVE-2014-9635 (published 2017-09-12T14:29Z)

Jenkins before 1.586 does not set the HttpOnly flag in a Set-Cookie header for session cookies when run on Tomcat 7.0.41 or later, which makes it easier for remote attackers to obtain potentially sensitive information via script access to cookies.

Severity: MEDIUM
CVSS v2 base score: 5.0 (AV:N/AC:L/Au:N/C:P/I:N/A:N)
CVSS v3 base score: 5.3, MEDIUM (CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N)

Weakness information:
cwe_id: CWE-254
cwe_name: 7PK - Security Features
description: Software security is not security software. Here we're concerned with topics like authentication, access control, confidentiality, cryptography, and privilege management.

Fix information:
repo_url: https://github.com/jenkinsci/jenkins
commit_details: repo_url: https://github.com/jenkinsci/jenkins
author: Kohsuke Kawaguchi
author_date: 2014-10-16 19:15:56-07:00
msg: [FIXED JENKINS-25019]

A truly conforming servlet 3.0 container does not allow us to set "secure cookie" flag beyond ServletContextListener.onInitialized().
If we see that, don't scare the users.
repository: repo_url: https://github.com/jenkinsci/jenkins
repo_name: jenkinsci/jenkins
description: Jenkins automation server
repo_language: Java
owner: jenkinsci
file_changes: filename: changelog.html
change_type: ModificationType.MODIFY
diff: @@ -61,6 +61,10 @@ Upcoming changes</a>
   <li class=bug>
     Prevent empty file creation if file parameter is left empty.
     (<a href="https://issues.jenkins-ci.org/browse/JENKINS-3539">issue 3539</a>)
+  <li class=bug>
+    Servlet containers may refuse to let us set <a href="https://www.owasp.org/index.php/SecureFlag">secure cookie flag</a>.
+    Deal with it gracefully.
+    (<a href="https://issues.jenkins-ci.org/browse/JENKINS-25019">issue 25019</a>)
 </ul>
 </div><!--=TRUNK-END=-->
 

programming_language: HTML
filename: WebAppMain.java
change_type: ModificationType.MODIFY
diff: @@ -56,6 +56,7 @@ import javax.xml.transform.TransformerFactoryConfigurationError;
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.lang.reflect.Method;
 import java.net.URL;
 import java.net.URLClassLoader;
 import java.util.Date;
@@ -116,6 +117,8 @@ public class WebAppMain implements ServletContextListener {
 
             installLogger();
 
+            markCookieAsHttpOnly(context);
+
             final FileAndDescription describedHomeDir = getHomeDir(event);
             home = describedHomeDir.file.getAbsoluteFile();
             home.mkdirs();
@@ -251,6 +254,31 @@ public class WebAppMain implements ServletContextListener {
         }
     }
 
+    /**
+     * Set the session cookie as HTTP only.
+     *
+     * @see <a href="https://www.owasp.org/index.php/HttpOnly">discussion of this topic in OWASP</a>
+     */
+    private void markCookieAsHttpOnly(ServletContext context) {
+        try {
+            Method m;
+            try {
+                m = context.getClass().getMethod("getSessionCookieConfig");
+            } catch (NoSuchMethodException x) { // 3.0+
+                LOGGER.log(Level.FINE, "Failed to set secure cookie flag", x);
+                return;
+            }
+            Object sessionCookieConfig = m.invoke(context);
+
+            // not exposing session cookie to JavaScript to mitigate damage caused by XSS
+            Class scc = Class.forName("javax.servlet.SessionCookieConfig");
+            Method setHttpOnly = scc.getMethod("setHttpOnly",boolean.class);
+            setHttpOnly.invoke(sessionCookieConfig,true);
+        } catch (Exception e) {
+            LOGGER.log(Level.WARNING, "Failed to set HTTP-only cookie flag", e);
+        }
+    }
+
     public void joinInit() throws InterruptedException {
         initThread.join();
     }

programming_language: Java
filename: JenkinsLocationConfiguration.java
change_type: ModificationType.MODIFY
diff: @@ -14,6 +14,7 @@ import javax.mail.internet.InternetAddress;
 import javax.servlet.ServletContext;
 import java.io.File;
 import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.util.logging.Level;
 import java.util.logging.Logger;
@@ -117,14 +118,17 @@ public class JenkinsLocationConfiguration extends GlobalConfiguration {
             }
             Object sessionCookieConfig = m.invoke(context);
 
-            // not exposing session cookie to JavaScript to mitigate damage caused by XSS
             Class scc = Class.forName("javax.servlet.SessionCookieConfig");
-            Method setHttpOnly = scc.getMethod("setHttpOnly",boolean.class);
-            setHttpOnly.invoke(sessionCookieConfig,true);
-
-            Method setSecure = scc.getMethod("setSecure",boolean.class);
+            Method setSecure = scc.getMethod("setSecure", boolean.class);
             boolean v = fixNull(jenkinsUrl).startsWith("https");
-            setSecure.invoke(sessionCookieConfig,v);
+            setSecure.invoke(sessionCookieConfig, v);
+        } catch (InvocationTargetException e) {
+            if (e.getTargetException() instanceof IllegalStateException) {
+                // servlet 3.0 spec seems to prohibit this from getting set at runtime,
+                // though Winstone is happy to accept i. see JENKINS-25019
+                return;
+            }
+            LOGGER.log(Level.WARNING, "Failed to set secure cookie flag", e);
         } catch (Exception e) {
             LOGGER.log(Level.WARNING, "Failed to set secure cookie flag", e);
         }

programming_language: Java