From 1e51b62298d37753f6b2d2f70eb179ab950d1456 Mon Sep 17 00:00:00 2001 From: Jesse Glick Date: Wed, 24 Apr 2013 18:32:01 -0400 Subject: [PATCH] [SECURITY-63] Check RUN_SCRIPTS for /eval.(cherry picked from commit 3d03990abc68f39e7a92ed9594abb658879a6d7b) --- core/src/main/java/jenkins/model/Jenkins.java | 2 +- .../test/java/jenkins/model/JenkinsTest.java | 40 +++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/jenkins/model/Jenkins.java b/core/src/main/java/jenkins/model/Jenkins.java index 6fd22fd149..b2efe0caa5 100755 --- a/core/src/main/java/jenkins/model/Jenkins.java +++ b/core/src/main/java/jenkins/model/Jenkins.java @@ -3398,7 +3398,7 @@ public class Jenkins extends AbstractCIBase implements ModifiableTopLevelItemGro */ @RequirePOST public void doEval(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException { - checkPermission(ADMINISTER); + checkPermission(RUN_SCRIPTS); try { MetaClass mc = WebApp.getCurrent().getMetaClass(getClass()); diff --git a/test/src/test/java/jenkins/model/JenkinsTest.java b/test/src/test/java/jenkins/model/JenkinsTest.java index 6859e83b58..250d9591f5 100644 --- a/test/src/test/java/jenkins/model/JenkinsTest.java +++ b/test/src/test/java/jenkins/model/JenkinsTest.java @@ -23,6 +23,7 @@ */ package jenkins.model; +import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException; import com.gargoylesoftware.htmlunit.HttpMethod; import com.gargoylesoftware.htmlunit.WebRequestSettings; import com.gargoylesoftware.htmlunit.html.HtmlForm; @@ -273,6 +274,45 @@ public class JenkinsTest extends HudsonTestCase { wc.assertFails("script", HttpURLConnection.HTTP_FORBIDDEN); } + public void testDoEval() throws Exception { + jenkins.setSecurityRealm(new LegacySecurityRealm()); + GlobalMatrixAuthorizationStrategy gmas = new GlobalMatrixAuthorizationStrategy() { + @Override public boolean hasPermission(String sid, Permission p) { + return p == Jenkins.RUN_SCRIPTS ? hasExplicitPermission(sid, p) : super.hasPermission(sid, p); + } + }; + gmas.add(Jenkins.ADMINISTER, "alice"); + gmas.add(Jenkins.RUN_SCRIPTS, "alice"); + gmas.add(Jenkins.READ, "bob"); + gmas.add(Jenkins.ADMINISTER, "charlie"); + jenkins.setAuthorizationStrategy(gmas); + // Otherwise get "RuntimeException: Trying to set the request parameters, but the request body has already been specified;the two are mutually exclusive!" from WebRequestSettings.setRequestParameters when POSTing content: + jenkins.setCrumbIssuer(null); + WebClient wc = createWebClient(); + wc.login("alice"); + wc.assertFails("eval", HttpURLConnection.HTTP_INTERNAL_ERROR); + assertEquals("3", eval(wc)); + wc.login("bob"); + try { + eval(wc); + fail("bob has only READ"); + } catch (FailingHttpStatusCodeException e) { + assertEquals(HttpURLConnection.HTTP_FORBIDDEN, e.getStatusCode()); + } + wc.login("charlie"); + try { + eval(wc); + fail("charlie has ADMINISTER but not RUN_SCRIPTS"); + } catch (FailingHttpStatusCodeException e) { + assertEquals(HttpURLConnection.HTTP_FORBIDDEN, e.getStatusCode()); + } + } + private String eval(WebClient wc) throws Exception { + WebRequestSettings req = new WebRequestSettings(new URL(wc.getContextPath() + "eval"), HttpMethod.POST); + req.setRequestBody("${1+2}"); + return wc.getPage(/*wc.addCrumb(*/req/*)*/).getWebResponse().getContentAsString(); + } + @TestExtension("testUnprotectedRootAction") public static class RootActionImpl implements UnprotectedRootAction { private int count; -- GitLab