Skip to content

Commit

Permalink
SECURITY-2189
Browse files Browse the repository at this point in the history
  • Loading branch information
Pldi23 committed Dec 9, 2021
1 parent 40947f2 commit 9c08b9f
Show file tree
Hide file tree
Showing 3 changed files with 150 additions and 7 deletions.
Expand Up @@ -44,6 +44,7 @@
import hudson.model.Queue;
import hudson.model.queue.Tasks;
import hudson.security.ACL;
import hudson.security.AccessControlled;
import hudson.tasks.BuildWrapper;
import hudson.tasks.BuildWrapperDescriptor;
import hudson.util.IOException2;
Expand All @@ -63,8 +64,9 @@
import javax.annotation.Nonnull;
import jenkins.model.Jenkins;
import org.apache.commons.lang.StringUtils;
import org.kohsuke.stapler.AncestorInPath;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.Stapler;
import org.kohsuke.stapler.QueryParameter;

/**
* A build wrapper that provides an SSH agent using supplied credentials
Expand Down Expand Up @@ -496,8 +498,11 @@ public String getDisplayName() {
* @return the list box model.
*/
@SuppressWarnings("unused") // used by stapler
public ListBoxModel doFillIdItems() {
Item item = Stapler.getCurrentRequest().findAncestorObject(Item.class);
public ListBoxModel doFillIdItems(@AncestorInPath Item item) {
AccessControlled contextToCheck = item == null ? Jenkins.get() : item;
if (!contextToCheck.hasPermission(CredentialsProvider.VIEW)) {
return new StandardUsernameListBoxModel();
}
return new StandardUsernameListBoxModel()
.includeMatchingAs(
item instanceof Queue.Task ? Tasks.getAuthenticationOf((Queue.Task) item) : ACL.SYSTEM,
Expand All @@ -507,7 +512,6 @@ public ListBoxModel doFillIdItems() {
SSHAuthenticator.matcher()
);
}

}
}

Expand Down
Expand Up @@ -10,12 +10,15 @@
import hudson.model.Queue;
import hudson.model.queue.Tasks;
import hudson.security.ACL;
import hudson.security.AccessControlled;
import hudson.util.ListBoxModel;
import jenkins.model.Jenkins;
import org.jenkinsci.plugins.workflow.steps.AbstractStepDescriptorImpl;
import org.jenkinsci.plugins.workflow.steps.AbstractStepImpl;
import org.kohsuke.stapler.AncestorInPath;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.DataBoundSetter;
import org.kohsuke.stapler.Stapler;
import org.kohsuke.stapler.QueryParameter;

import java.io.Serializable;
import java.util.Collections;
Expand Down Expand Up @@ -76,8 +79,11 @@ public boolean takesImplicitBlockArgument() {
* @return the list box model.
*/
@SuppressWarnings("unused") // used by stapler
public ListBoxModel doFillCredentialsItems() {
Item item = Stapler.getCurrentRequest().findAncestorObject(Item.class);
public ListBoxModel doFillCredentialsItems(@AncestorInPath Item item) {
AccessControlled contextToCheck = item == null ? Jenkins.get() : item;
if (!contextToCheck.hasPermission(CredentialsProvider.VIEW)) {
return new StandardUsernameListBoxModel();
}
return new StandardUsernameListBoxModel()
.includeMatchingAs(
item instanceof Queue.Task ? Tasks.getAuthenticationOf((Queue.Task)item) : ACL.SYSTEM,
Expand Down
@@ -0,0 +1,133 @@
package com.cloudbees.jenkins.plugins.sshagent;

import com.cloudbees.jenkins.plugins.sshcredentials.SSHUserPrivateKey;
import com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey;
import com.cloudbees.plugins.credentials.CredentialsScope;
import com.cloudbees.plugins.credentials.SystemCredentialsProvider;
import hudson.model.FreeStyleProject;
import hudson.model.Item;
import hudson.model.User;
import hudson.security.ACL;
import hudson.security.ACLContext;
import hudson.util.ListBoxModel;
import jenkins.model.Jenkins;
import org.jenkinsci.plugins.workflow.job.WorkflowJob;
import org.junit.Rule;
import org.junit.Test;
import org.jvnet.hudson.test.Issue;
import org.jvnet.hudson.test.JenkinsRule;
import org.jvnet.hudson.test.MockAuthorizationStrategy;

import java.io.IOException;

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.hasSize;

/**
* Test if there is any information disclosure
*/
public class Security2189Test {

private static final String SECURE_DATA = "SecureData";
private static final String TEST_NAME = "test";
private static final String ADMINISTER_NAME = "administer";
private static final String WITHOUT_ANY_PERMISSION_USER_NAME = "WithoutAnyPermissionUser";

@Rule
public JenkinsRule r = new JenkinsRule();

private WorkflowJob job;
private FreeStyleProject project;

@Issue("SECURITY-2189")
@Test
public void doFillCredentialsItemsWhenAdminThenListPopulatedWithNameAndId() throws IOException {
setUpAuthorizationAndWorkflowJob();
initCredentials(SECURE_DATA, TEST_NAME);

try(ACLContext aclContext = ACL.as(User.getOrCreateByIdOrFullName(ADMINISTER_NAME))) {
SSHAgentStep.DescriptorImpl descriptor = (SSHAgentStep.DescriptorImpl) Jenkins.get().getDescriptorOrDie(SSHAgentStep.class);
ListBoxModel secureData = descriptor.doFillCredentialsItems(job);
ListBoxModel expected = new ListBoxModel(new ListBoxModel.Option(TEST_NAME, SECURE_DATA));

assertListBoxModel(secureData, expected);
}
}

@Issue("SECURITY-2189")
@Test
public void doFillCredentialsItemsWhenUserWithoutAnyCredentialsThenListNotPopulated() throws Exception {
setUpAuthorizationAndWorkflowJob();
initCredentials(SECURE_DATA, TEST_NAME);

try(ACLContext aclContext = ACL.as(User.getOrCreateByIdOrFullName(WITHOUT_ANY_PERMISSION_USER_NAME))) {
SSHAgentStep.DescriptorImpl descriptor = (SSHAgentStep.DescriptorImpl) Jenkins.get().getDescriptorOrDie(SSHAgentStep.class);
ListBoxModel secureData = descriptor.doFillCredentialsItems(job);

assertThat(secureData, is(empty()));
}
}

@Issue("SECURITY-2189")
@Test
public void doFillIdItemsWhenAdminThenListPopulated() throws IOException {
setUpAuthorizationAndFreestyleProject();
initCredentials(SECURE_DATA, TEST_NAME);

try(ACLContext aclContext = ACL.as(User.getOrCreateByIdOrFullName(ADMINISTER_NAME))) {
SSHAgentBuildWrapper.CredentialHolder.DescriptorImpl descriptor = (SSHAgentBuildWrapper.CredentialHolder.DescriptorImpl) Jenkins.get().getDescriptorOrDie(SSHAgentBuildWrapper.CredentialHolder.class);
ListBoxModel secureData = descriptor.doFillIdItems(project);
ListBoxModel expected = new ListBoxModel(new ListBoxModel.Option(TEST_NAME, SECURE_DATA));

assertListBoxModel(secureData, expected);
}
}

@Issue("SECURITY-2189")
@Test
public void doFillIdItemsWhenUserWithoutAnyPermissionThenListNotPopulated() throws Exception {
setUpAuthorizationAndWorkflowJob();
initCredentials(SECURE_DATA, TEST_NAME);

try(ACLContext aclContext = ACL.as(User.getOrCreateByIdOrFullName(WITHOUT_ANY_PERMISSION_USER_NAME))) {
SSHAgentBuildWrapper.CredentialHolder.DescriptorImpl descriptor = (SSHAgentBuildWrapper.CredentialHolder.DescriptorImpl) Jenkins.get().getDescriptorOrDie(SSHAgentBuildWrapper.CredentialHolder.class);
ListBoxModel secureData = descriptor.doFillIdItems(project);

assertThat(secureData, is(empty()));
}
}

private void setUpAuthorizationAndWorkflowJob() throws IOException {
job = r.jenkins.createProject(WorkflowJob.class, "j");
setUpAuthorization(job);
}

private void setUpAuthorizationAndFreestyleProject() throws IOException {
project = r.jenkins.createProject(FreeStyleProject.class, "p");
setUpAuthorization(project);
}

private void setUpAuthorization(Item... items) {
r.jenkins.setSecurityRealm(r.createDummySecurityRealm());
r.jenkins.setAuthorizationStrategy(new MockAuthorizationStrategy()
.grant(Jenkins.ADMINISTER).everywhere().to(ADMINISTER_NAME)
.grant().onItems(items).to(WITHOUT_ANY_PERMISSION_USER_NAME));
}

private static void assertListBoxModel(ListBoxModel actual, ListBoxModel expected) {
assertThat(actual, is(not(empty())));
assertThat(actual, hasSize(expected.size()));
assertThat(actual.get(0).name, is(expected.get(0).name));
assertThat(actual.get(0).value, is(expected.get(0).value));
}

private static void initCredentials(String credentialsId, String name) throws IOException {
SSHUserPrivateKey key = new BasicSSHUserPrivateKey(CredentialsScope.GLOBAL, credentialsId, "cloudbees",
null, "* .*", name);
SystemCredentialsProvider.getInstance().getCredentials().add(key);
SystemCredentialsProvider.getInstance().save();
}
}

0 comments on commit 9c08b9f

Please sign in to comment.