Stored XSS vulnerability in Jenkins console links
Research is free — Hunters explains how the bug works, the root-cause code pattern, how the fix addresses it, and how to test whether a target is affected, in chat. Investigate & write exploit is a paid run — the engine reads the advisory and fix commits, then builds and validates a working proof-of-concept exploit with reproduction steps.
Affected versions
0 → fixed in 2.235.22.236 → fixed in 2.245
Details
Jenkins 2.244 and earlier, LTS 2.235.1 and earlier does not escape the `href` attribute of links to downstream jobs displayed in the build console page. This results in a stored cross-site scripting (XSS) vulnerability exploitable by users with Job/Configure permission. Jenkins 2.245, LTS 2.235.2 escapes the `href` attribute of these links.
The fix
[SECURITY-1945]
core/src/main/java/hudson/console/HyperlinkNote.java+2 −1
@@ -25,6 +25,7 @@import hudson.Extension;import hudson.MarkupText;+import hudson.Util;import jenkins.model.Jenkins;import org.jenkinsci.Symbol;import org.kohsuke.accmod.Restricted;@@ -69,7 +70,7 @@ public ConsoleAnnotator annotate(Object context, MarkupText text, int charPos) {url = Jenkins.get().getRootUrl()+url.substring(1);}}-text.addMarkup(charPos, charPos + length, "<a href='" + url + "'"+extraAttributes()+">", "</a>");+text.addMarkup(charPos, charPos + length, "<a href='" + Util.escape(url) + "'"+extraAttributes()+">", "</a>");return null;}
test/src/test/java/hudson/console/HyperlinkNoteTest.java+18 −0
@@ -24,11 +24,16 @@package hudson.console;+import com.gargoylesoftware.htmlunit.html.HtmlPage;+import hudson.model.FreeStyleBuild;import hudson.model.FreeStyleProject;import java.io.IOException;import java.io.StringReader;import java.io.StringWriter;import java.nio.charset.StandardCharsets;++import hudson.model.Result;+import hudson.tasks.BuildTrigger;import org.apache.commons.io.IOUtils;import org.junit.Rule;import org.junit.Test;@@ -73,6 +78,19 @@ public void textWithNewlinesModelHyperlinkNote() throws Exception {containsString(">" + noteTextSanitized + "</a>")));}+@Test+public void textWithSingleQuote() throws Exception {+FreeStyleProject upstream = r.createFreeStyleProject("upstream");+r.createFreeStyleProject("d0wnstr3'am");+upstream.getPublishersList().add(new BuildTrigger("d0wnstr3'am", Result.SUCCESS));+r.jenkins.rebuildDependencyGraph();+FreeStyleBuild b = r.buildAndAssertSuccess(upstream);+r.waitUntilNoActivity();+HtmlPage rsp = r.createWebClient().goTo(b.getUrl()+"console");+assertThat(rsp.querySelector(".console-output").asText(), containsString("Triggering a new build of"));+assertThat(String.valueOf(rsp.getAnchorByText("d0wnstr3'am").click().getWebResponse().getStatusCode()), containsString("200"));+}+private static String annotate(String text) throws IOException {StringWriter writer = new StringWriter();try (ConsoleAnnotationOutputStream out = new ConsoleAnnotationOutputStream(writer, null, null, StandardCharsets.UTF_8)) {
References
- ADVISORYhttps://nvd.nist.gov/vuln/detail/CVE-2020-2223
- WEBhttps://github.com/jenkinsci/jenkins/commit/11f4a351224ef04cfeb9c7636fb1590b67543f3c
- PACKAGEhttps://github.com/jenkinsci/jenkins
- WEBhttps://jenkins.io/security/advisory/2020-07-15/#SECURITY-1945
- WEBhttp://www.openwall.com/lists/oss-security/2020/07/15/5