mirror of
https://github.com/jenkinsci/jenkins.git
synced 2026-11-15 13:02:19 +00:00
[SECURITY-3669]
This commit is contained in:
1 parent
f92eadb581
commit
578c028e2c
3 files changed
+162
-1
No files matched your search
@@ -26,6 +26,7 @@ package hudson.slaves;
|
||||
|
||||
import edu.umd.cs.findbugs.annotations.CheckForNull;
|
||||
import edu.umd.cs.findbugs.annotations.NonNull;
|
||||
import hudson.Util;
|
||||
import hudson.model.Computer;
|
||||
import hudson.model.User;
|
||||
import java.io.ObjectStreamException;
|
||||
@@ -166,7 +167,7 @@ public abstract class OfflineCause implements IOfflineCause {
|
||||
* @return the message that was provided when the computer was taken offline
|
||||
*/
|
||||
public String getMessage() {
|
||||
return message;
|
||||
return Util.escape(message);
|
||||
}
|
||||
|
||||
// Storing the User in a filed was a mistake, switch to userId
|
||||
@@ -202,6 +203,11 @@ public abstract class OfflineCause implements IOfflineCause {
|
||||
public String getIcon() {
|
||||
return "symbol-person";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return Util.escape(super.toString());
|
||||
}
|
||||
}
|
||||
|
||||
public static class ByCLI extends UserCause {
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
package jenkins.security;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.allOf;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
|
||||
import hudson.model.Computer;
|
||||
import hudson.model.User;
|
||||
import hudson.slaves.DumbSlave;
|
||||
import hudson.slaves.OfflineCause;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import jenkins.model.Jenkins;
|
||||
import org.htmlunit.html.HtmlFormUtil;
|
||||
import org.htmlunit.html.HtmlPage;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.jvnet.hudson.test.JenkinsRule;
|
||||
import org.jvnet.hudson.test.junit.jupiter.WithJenkins;
|
||||
import org.jvnet.hudson.test.junit.jupiter.WithLocalData;
|
||||
|
||||
@WithJenkins
|
||||
public class Security3669Test {
|
||||
@Test
|
||||
public void newOfflineCause(JenkinsRule jenkinsRule) throws Exception {
|
||||
try (JenkinsRule.WebClient webClient = jenkinsRule.createWebClient()) {
|
||||
HtmlPage formPage = webClient.getPage(Jenkins.get(), "markOffline");
|
||||
formPage.getElementByName("offlineMessage").setTextContent("<img src=x onerror=alert(1)>");
|
||||
HtmlFormUtil.submit(formPage.getForms().stream().filter(f -> f.getActionAttribute().equals("toggleOffline")).findFirst().orElseThrow());
|
||||
|
||||
final HtmlPage nodePage = webClient.getPage(Jenkins.get());
|
||||
assertThat(
|
||||
nodePage.getWebResponse().getContentAsString(),
|
||||
allOf(
|
||||
not(containsString("<img src=x onerror=alert(1)>")),
|
||||
containsString("Disconnected by anonymous : <img src=x onerror=alert(1)>")));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void editOfflineCause(JenkinsRule jenkinsRule) throws Exception {
|
||||
Jenkins.get().getComputer("").setTemporaryOfflineCause(new OfflineCause.UserCause(User.current(), "initial reason"));
|
||||
try (JenkinsRule.WebClient webClient = jenkinsRule.createWebClient()) {
|
||||
HtmlPage formPage = webClient.getPage(Jenkins.get(), "setOfflineCause");
|
||||
formPage.getElementByName("offlineMessage").setTextContent("<img src=x onerror=alert(1)>");
|
||||
HtmlFormUtil.submit(formPage.getForms().stream().filter(f -> f.getActionAttribute().equals("changeOfflineCause")).findFirst().orElseThrow());
|
||||
|
||||
final HtmlPage nodePage = webClient.getPage(Jenkins.get());
|
||||
assertThat(
|
||||
nodePage.getWebResponse().getContentAsString(),
|
||||
allOf(
|
||||
not(containsString("<img src=x onerror=alert(1)>")),
|
||||
containsString("Disconnected by anonymous : <img src=x onerror=alert(1)>")));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void postConfigXmlWithLocalizable(JenkinsRule jenkinsRule) throws Exception {
|
||||
final DumbSlave agent = jenkinsRule.createOnlineSlave();
|
||||
|
||||
String xml = "<?xml version=\"1.1\" encoding=\"UTF-8\"?>\n" +
|
||||
"<slave>\n" +
|
||||
" <temporaryOfflineCause class=\"hudson.slaves.OfflineCause$UserCause\">\n" +
|
||||
" <timestamp>1770000000000</timestamp>\n" +
|
||||
" <description>\n" +
|
||||
" <holder>\n" +
|
||||
" <owner>hudson.slaves.Messages</owner>\n" +
|
||||
" </holder>\n" +
|
||||
" <key>SlaveComputer.DisconnectedBy</key>\n" +
|
||||
" <args>\n" +
|
||||
" <string>admin</string>\n" +
|
||||
" <string> : <img src=x onerror=alert(1)></string>\n" +
|
||||
" </args>\n" +
|
||||
" </description>\n" +
|
||||
" <userId>admin</userId>\n" +
|
||||
" <message><img src=x onerror=alert(1)></message>\n" +
|
||||
" </temporaryOfflineCause>\n" +
|
||||
" <name>" + agent.getNodeName() + "</name>\n" +
|
||||
" <description></description>\n" +
|
||||
" <remoteFS>/tmp/foo</remoteFS>\n" +
|
||||
" <numExecutors>1</numExecutors>\n" +
|
||||
" <mode>NORMAL</mode>\n" +
|
||||
" <retentionStrategy class=\"hudson.slaves.RetentionStrategy$Always\"/>\n" +
|
||||
" <launcher class=\"hudson.slaves.JNLPLauncher\">\n" +
|
||||
" <workDirSettings>\n" +
|
||||
" <disabled>false</disabled>\n" +
|
||||
" <internalDir>remoting</internalDir>\n" +
|
||||
" <failIfWorkDirIsMissing>false</failIfWorkDirIsMissing>\n" +
|
||||
" </workDirSettings>\n" +
|
||||
" <webSocket>false</webSocket>\n" +
|
||||
" </launcher>\n" +
|
||||
" <label></label>\n" +
|
||||
" <nodeProperties/>\n" +
|
||||
"</slave>";
|
||||
agent.toComputer().updateByXml(new ByteArrayInputStream(xml.getBytes()));
|
||||
|
||||
try (JenkinsRule.WebClient webClient = jenkinsRule.createWebClient()) {
|
||||
final HtmlPage nodePage = webClient.getPage(agent);
|
||||
assertThat(
|
||||
nodePage.getWebResponse().getContentAsString(),
|
||||
allOf(
|
||||
not(containsString("<img src=x onerror=alert(1)>")),
|
||||
containsString("Disconnected by admin : <img src=x onerror=alert(1)>")));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithLocalData
|
||||
void dataFromDisk(JenkinsRule jenkinsRule) throws Exception {
|
||||
final Computer agent = jenkinsRule.jenkins.getComputer("a1");
|
||||
assertThat(agent, not(nullValue()));
|
||||
|
||||
try (JenkinsRule.WebClient webClient = jenkinsRule.createWebClient()) {
|
||||
final HtmlPage nodePage = webClient.getPage(agent.getNode());
|
||||
assertThat(
|
||||
nodePage.getWebResponse().getContentAsString(),
|
||||
allOf(
|
||||
not(containsString("<img src=x onerror=alert(1)>")),
|
||||
containsString("Disconnected by anonymous : <img src=x onerror=alert(1)>")));
|
||||
}
|
||||
}
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
<?xml version='1.1' encoding='UTF-8'?>
|
||||
<slave>
|
||||
<temporaryOfflineCause class="hudson.slaves.OfflineCause$UserCause">
|
||||
<timestamp>1770000000000</timestamp>
|
||||
<description>
|
||||
<holder>
|
||||
<owner>hudson.slaves.Messages</owner>
|
||||
</holder>
|
||||
<key>SlaveComputer.DisconnectedBy</key>
|
||||
<args>
|
||||
<string>anonymous</string>
|
||||
<string> : <img src=x onerror=alert(1)></string>
|
||||
</args>
|
||||
</description>
|
||||
<message><img src=x onerror=alert(1)></message>
|
||||
</temporaryOfflineCause>
|
||||
<name>a1</name>
|
||||
<description></description>
|
||||
<remoteFS>/tmp/a1</remoteFS>
|
||||
<numExecutors>1</numExecutors>
|
||||
<mode>NORMAL</mode>
|
||||
<retentionStrategy class="hudson.slaves.RetentionStrategy$Always"/>
|
||||
<launcher class="hudson.slaves.JNLPLauncher">
|
||||
<workDirSettings>
|
||||
<disabled>false</disabled>
|
||||
<internalDir>remoting</internalDir>
|
||||
<failIfWorkDirIsMissing>false</failIfWorkDirIsMissing>
|
||||
</workDirSettings>
|
||||
<webSocket>false</webSocket>
|
||||
</launcher>
|
||||
<label></label>
|
||||
<nodeProperties/>
|
||||
</slave>
|
||||
Reference in new issue
Block a user