diff --git a/core/src/main/java/hudson/Plugin.java b/core/src/main/java/hudson/Plugin.java index 58026cbb32cd..bfbac02d9176 100644 --- a/core/src/main/java/hudson/Plugin.java +++ b/core/src/main/java/hudson/Plugin.java @@ -228,7 +228,7 @@ public void doDynamic(StaplerRequest req, StaplerResponse rsp) throws IOExceptio String path = req.getRestOfPath(); String pathUC = path.toUpperCase(Locale.ENGLISH); - if (path.isEmpty() || path.contains("..") || path.contains("%") || pathUC.contains("META-INF") || pathUC.contains("WEB-INF")) { + if (path.isEmpty() || path.contains("..") || path.startsWith(".") || path.contains("%") || pathUC.contains("META-INF") || pathUC.contains("WEB-INF")) { LOGGER.warning("rejecting possibly malicious " + req.getRequestURIWithQueryString()); rsp.sendError(HttpServletResponse.SC_BAD_REQUEST); return; diff --git a/test/src/test/java/hudson/PluginTest.java b/test/src/test/java/hudson/PluginTest.java index 6c806174e956..17f7329e0013 100644 --- a/test/src/test/java/hudson/PluginTest.java +++ b/test/src/test/java/hudson/PluginTest.java @@ -39,17 +39,17 @@ public class PluginTest { @Test public void doDynamic() throws Exception { ((TestPluginManager) r.jenkins.pluginManager).installDetachedPlugin("credentials"); r.createWebClient().goTo("plugin/credentials/images/24x24/credentials.png", "image/png"); - /* Collapsed somewhere before it winds up in restOfPath: - r.createWebClient().assertFails("plugin/credentials/images/../images/24x24/credentials.png", HttpServletResponse.SC_BAD_REQUEST); - */ + r.createWebClient().goTo("plugin/credentials/images/../images/24x24/credentials.png", "image/png"); // collapsed somewhere before it winds up in restOfPath r.createWebClient().assertFails("plugin/credentials/images/%2E%2E/images/24x24/credentials.png", HttpServletResponse.SC_INTERNAL_SERVER_ERROR); // IAE from TokenList. r.createWebClient().assertFails("plugin/credentials/images/%252E%252E/images/24x24/credentials.png", HttpServletResponse.SC_BAD_REQUEST); // SECURITY-131 r.createWebClient().assertFails("plugin/credentials/images/%25252E%25252E/images/24x24/credentials.png", HttpServletResponse.SC_BAD_REQUEST); // just checking // SECURITY-705: r.createWebClient().assertFails("plugin/credentials/images/..%2fWEB-INF/licenses.xml", HttpServletResponse.SC_BAD_REQUEST); + r.createWebClient().assertFails("plugin/credentials/./credentials.jpi", /* Path collapsed to simply `credentials.jpi` before entering */ HttpServletResponse.SC_NOT_FOUND); r.createWebClient().assertFails("plugin/credentials/images/%2e%2e%2fWEB-INF/licenses.xml", HttpServletResponse.SC_BAD_REQUEST); r.createWebClient().assertFails("plugin/credentials/images/%2e.%2fWEB-INF/licenses.xml", HttpServletResponse.SC_BAD_REQUEST); r.createWebClient().assertFails("plugin/credentials/images/..%2f..%2f..%2f" + r.jenkins.getRootDir().getName() + "%2fsecrets%2fmaster.key", HttpServletResponse.SC_BAD_REQUEST); + r.createWebClient().assertFails("plugin/credentials/" + r.jenkins.getRootDir() + "/secrets/master.key", /* ./ prepended anyway */ HttpServletResponse.SC_NOT_FOUND); // SECURITY-155: r.createWebClient().assertFails("plugin/credentials/WEB-INF/licenses.xml", HttpServletResponse.SC_BAD_REQUEST); r.createWebClient().assertFails("plugin/credentials/META-INF/MANIFEST.MF", HttpServletResponse.SC_BAD_REQUEST);