CVE-2013-0158: Insufficient Information (NVD-CWE-noinfo)
value: Unspecified vulnerability in Jenkins before 1.498, Jenkins LTS before 1.480.2, and Jenkins Enterprise 1.447.x before 1.447.6.1 and 1.466.x before 1.466.12.1, when a slave is attached and anonymous read access is enabled, allows remote attackers to obtain the master cryptographic key via unknown vectors.
CWE description: There is insufficient information about the issue to classify it; details are unkown or unspecified.
Published: 2013-02-24T22:55Z
Repository: https://github.com/jenkinsci/jenkins
Language: Java
Files changed: core/src/main/java/jenkins/security/ConfidentialStore.java, core/src/main/java/jenkins/security/DefaultConfidentialStore.java
Commit date: 2013-01-05 14:28:57 -0800
Commit message: [SECURITY-49] Backing off from @Extension-based discovery.

This is because we discovered some plugins that use Secret early on in
the initialization.

Diff: diff --git a/core/src/main/java/jenkins/security/ConfidentialStore.java b/core/src/main/java/jenkins/security/ConfidentialStore.java
index 0c768f0af..de8243765 100644
--- a/core/src/main/java/jenkins/security/ConfidentialStore.java
+++ b/core/src/main/java/jenkins/security/ConfidentialStore.java
@@ -1,14 +1,22 @@
 package jenkins.security;
 
 import hudson.Extension;
+import hudson.Lookup;
+import hudson.init.InitMilestone;
+import hudson.util.Secret;
+import hudson.util.Service;
 import jenkins.model.Jenkins;
+import org.kohsuke.MetaInfServices;
 
 import javax.annotation.CheckForNull;
 import javax.annotation.Nonnull;
 import java.io.IOException;
 import java.security.SecureRandom;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 
 /**
  * The actual storage for the data held by {@link ConfidentialKey}s, and the holder
  * of the master secret.
  *
@@ -16,12 +24,15 @@ import java.security.SecureRandom;
  * This class is only relevant for the implementers of {@link ConfidentialKey}s.
  * Most plugin code should interact with {@link ConfidentialKey}s.
  *
  * <p>
  * OEM distributions of Jenkins can provide a custom {@link ConfidentialStore} implementation
- * by writing a subclass, mark it with {@link Extension} annotation, package it as a Jenkins module,
- * and bundling it with the war file.
+ * by writing a subclass, mark it with {@link MetaInfServices} annotation, package it as a Jenkins module,
+ * and bundling it with the war file. This doesn't use {@link Extension} because some plugins
+ * have been found to use {@link Secret} before we get to {@link InitMilestone#PLUGINS_PREPARED}, and
+ * therefore {@link Extension}s aren't loaded yet. (Similarly, it's conceivable that some future
+ * core code might need this early on during the boot sequence.)
  *
  * @author Kohsuke Kawaguchi
  * @since 1.498
  */
 public abstract class ConfidentialStore {
@@ -49,13 +60,38 @@ public abstract class ConfidentialStore {
     /**
      * Retrieves the currently active singleton instance of {@link ConfidentialStore}.
      */
     public static @Nonnull ConfidentialStore get() {
         if (TEST!=null) return TEST.get();
-        return Jenkins.getInstance().getExtensionList(ConfidentialStore.class).get(0);
+
+        Lookup lookup = Jenkins.getInstance().lookup;
+        ConfidentialStore cs = lookup.get(ConfidentialStore.class);
+        if (cs==null) {
+            try {
+                List<ConfidentialStore> r = (List) Service.loadInstances(ConfidentialStore.class.getClassLoader(), ConfidentialStore.class);
+                if (!r.isEmpty())
+                    cs = r.get(0);
+            } catch (IOException e) {
+                LOGGER.log(Level.WARNING, "Failed to list up ConfidentialStore implementations",e);
+                // fall through
+            }
+
+            if (cs==null)
+                try {
+                    cs = new DefaultConfidentialStore();
+                } catch (Exception e) {
+                    // if it's still null, bail out
+                    throw new Error(e);
+                }
+
+            cs = lookup.setIfNull(ConfidentialStore.class,cs);
+        }
+        return cs;
     }
 
     /**
      * Testing only. Used for testing {@link ConfidentialKey} without {@link Jenkins}
      */
     /*package*/ static ThreadLocal<ConfidentialStore> TEST = null;
+
+    private static final Logger LOGGER = Logger.getLogger(ConfidentialStore.class.getName());
 }
diff --git a/core/src/main/java/jenkins/security/DefaultConfidentialStore.java b/core/src/main/java/jenkins/security/DefaultConfidentialStore.java
index 23e42c4d5..476f437f9 100644
--- a/core/src/main/java/jenkins/security/DefaultConfidentialStore.java
+++ b/core/src/main/java/jenkins/security/DefaultConfidentialStore.java
@@ -1,8 +1,7 @@
 package jenkins.security;
 
-import hudson.Extension;
 import hudson.FilePath;
 import hudson.Util;
 import hudson.util.IOException2;
 import hudson.util.IOUtils;
 import hudson.util.Secret;
@@ -26,11 +25,11 @@ import java.security.SecureRandom;
  *
  * The master key is also stored in this same directory.
  *
  * @author Kohsuke Kawaguchi
  */
-@Extension(ordinal=-99999) // small ordinal value to allow other higher ones to take over
+// @MetaInfServices --- not annotated because this is the fallback implementation
 public class DefaultConfidentialStore extends ConfidentialStore {
     private final SecureRandom sr = new SecureRandom();
 
     /**
      * Directory that stores individual keys.

Vulnerable code:  * by writing a subclass, mark it with {@link Extension} annotation, package it as a Jenkins module,
 * and bundling it with the war file.
        return Jenkins.getInstance().getExtensionList(ConfidentialStore.class).get(0);
import hudson.Extension;
@Extension(ordinal=-99999) // small ordinal value to allow other higher ones to take over
Fixed code: import hudson.Lookup;
import hudson.init.InitMilestone;
import hudson.util.Secret;
import hudson.util.Service;
import org.kohsuke.MetaInfServices;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
 * by writing a subclass, mark it with {@link MetaInfServices} annotation, package it as a Jenkins module,
 * and bundling it with the war file. This doesn't use {@link Extension} because some plugins
 * have been found to use {@link Secret} before we get to {@link InitMilestone#PLUGINS_PREPARED}, and
 * therefore {@link Extension}s aren't loaded yet. (Similarly, it's conceivable that some future
 * core code might need this early on during the boot sequence.)

        Lookup lookup = Jenkins.getInstance().lookup;
        ConfidentialStore cs = lookup.get(ConfidentialStore.class);
        if (cs==null) {
            try {
                List<ConfidentialStore> r = (List) Service.loadInstances(ConfidentialStore.class.getClassLoader(), ConfidentialStore.class);
                if (!r.isEmpty())
                    cs = r.get(0);
            } catch (IOException e) {
                LOGGER.log(Level.WARNING, "Failed to list up ConfidentialStore implementations",e);
                // fall through
            }

            if (cs==null)
                try {
                    cs = new DefaultConfidentialStore();
                } catch (Exception e) {
                    // if it's still null, bail out
                    throw new Error(e);
                }

            cs = lookup.setIfNull(ConfidentialStore.class,cs);
        }
        return cs;

    private static final Logger LOGGER = Logger.getLogger(ConfidentialStore.class.getName());
// @MetaInfServices --- not annotated because this is the fallback implementation