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

Jenkins before 1.586 does not set the secure flag on session cookies when run on Tomcat 7.0.41 or later, which makes it easier for remote attackers to capture cookies by intercepting their transmission within an HTTP session.

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