CVE-2014-2058 (published 2014-10-17T15:55Z)

BuildTrigger in Jenkins before 1.551 and LTS before 1.532.2 allows remote authenticated users to bypass access restrictions and execute arbitrary jobs by configuring a job to trigger another job. NOTE: this vulnerability exists because of an incomplete fix for CVE-2013-7330.

Severity: MEDIUM
CVSS v2 base score: 6.5 (AV:N/AC:L/Au:S/C:P/I:P/A:P)

Weakness information:
cwe_id: CWE-264
cwe_name: Permissions, Privileges, and Access Controls
description: Weaknesses in this category are related to the management of permissions, privileges, and other security features that are used to perform access control.

Fix information:
repo_url: https://github.com/jenkinsci/jenkins
commit_details: repo_url: https://github.com/jenkinsci/jenkins
author: Jesse Glick
author_date: 2014-02-10 19:13:32-05:00
msg: [FIXED SECURITY-109] SECURITY-55 fix to BuildTrigger configuration failed if downstream project was not visible.
repository: repo_url: https://github.com/jenkinsci/jenkins
repo_name: jenkinsci/jenkins
description: Jenkins automation server
repo_language: Java
owner: jenkinsci
file_changes: filename: AbstractProject.java
change_type: ModificationType.MODIFY
diff: @@ -1939,7 +1939,14 @@ public abstract class AbstractProject<P extends AbstractProject<P,R>,R extends A
 
         for (Publisher _t : Descriptor.newInstancesFromHeteroList(req, json, "publisher", Jenkins.getInstance().getExtensionList(BuildTrigger.DescriptorImpl.class))) {
             BuildTrigger t = (BuildTrigger) _t;
-            for (AbstractProject downstream : t.getChildProjects(this)) {
+            List<AbstractProject> childProjects;
+            SecurityContext orig = ACL.impersonate(ACL.SYSTEM);
+            try {
+                childProjects = t.getChildProjects(this);
+            } finally {
+                SecurityContextHolder.setContext(orig);
+            }
+            for (AbstractProject downstream : childProjects) {
                 downstream.checkPermission(BUILD);
             }
         }

programming_language: Java
filename: BuildTriggerTest.java
change_type: ModificationType.MODIFY
diff: @@ -23,14 +23,26 @@
  */
 package hudson.tasks;
 
+import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
 import com.gargoylesoftware.htmlunit.html.HtmlForm;
 import com.gargoylesoftware.htmlunit.html.HtmlPage;
+import com.gargoylesoftware.htmlunit.html.HtmlTextInput;
 import hudson.maven.MavenModuleSet;
 import hudson.maven.MavenModuleSetBuild;
 import hudson.model.FreeStyleBuild;
 import hudson.model.FreeStyleProject;
+import hudson.model.Item;
 import hudson.model.Result;
 import hudson.model.Run;
+import hudson.security.AuthorizationMatrixProperty;
+import hudson.security.LegacySecurityRealm;
+import hudson.security.Permission;
+import hudson.security.ProjectMatrixAuthorizationStrategy;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import jenkins.model.Jenkins;
 import org.jvnet.hudson.test.ExtractResourceSCM;
 import org.jvnet.hudson.test.HudsonTestCase;
 import org.jvnet.hudson.test.MockBuilder;
@@ -131,4 +143,36 @@ public class BuildTriggerTest extends HudsonTestCase {
     public void testMavenTriggerEvenWhenUnstable() throws Exception {
         doMavenTriggerTest(true);
     }
+
+    public void testConfigureDownstreamProjectSecurity() throws Exception {
+        jenkins.setSecurityRealm(new LegacySecurityRealm());
+        ProjectMatrixAuthorizationStrategy auth = new ProjectMatrixAuthorizationStrategy();
+        auth.add(Jenkins.READ, "alice");
+        jenkins.setAuthorizationStrategy(auth);
+        FreeStyleProject upstream = createFreeStyleProject("upstream");
+        Map<Permission,Set<String>> perms = new HashMap<Permission,Set<String>>();
+        perms.put(Item.READ, Collections.singleton("alice"));
+        perms.put(Item.CONFIGURE, Collections.singleton("alice"));
+        upstream.addProperty(new AuthorizationMatrixProperty(perms));
+        FreeStyleProject downstream = createFreeStyleProject("downstream");
+        /* Original SECURITY-55 test case:
+        downstream.addProperty(new AuthorizationMatrixProperty(Collections.singletonMap(Item.READ, Collections.singleton("alice"))));
+        */
+        WebClient wc = createWebClient();
+        wc.login("alice");
+        HtmlPage page = wc.getPage(upstream, "configure");
+        HtmlForm config = page.getFormByName("config");
+        config.getButtonByCaption("Add post-build action").click(); // lib/hudson/project/config-publishers2.jelly
+        page.getAnchorByText("Build other projects").click();
+        HtmlTextInput childProjects = config.getInputByName("buildTrigger.childProjects");
+        childProjects.setValueAttribute("downstream");
+        try {
+            submit(config);
+            fail();
+        } catch (FailingHttpStatusCodeException x) {
+            assertEquals(403, x.getStatusCode());
+        }
+        assertEquals(Collections.emptyList(), upstream.getDownstreamProjects());
+    }
+
 }

programming_language: Java