Skip to content

Commit 9e7b4c0

Browse files
committed
XWIKI-23109 XWIKI-19350: Improve resource validation
1 parent 0838101 commit 9e7b4c0

File tree

7 files changed

+135
-14
lines changed
  • xwiki-platform-core
    • xwiki-platform-flamingo/xwiki-platform-flamingo-skin/xwiki-platform-flamingo-skin-test/xwiki-platform-flamingo-skin-test-docker/src/test/it/org/xwiki/flamingo/test/docker
    • xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/internal/template
    • xwiki-platform-resource/xwiki-platform-resource-servlet/src/main/java/org/xwiki/resource/servlet
    • xwiki-platform-skin
      • xwiki-platform-skin-skinx/src/main/java/com/xpn/xwiki/web/sx
      • xwiki-platform-skin-test/xwiki-platform-skin-test-docker/src/test/it/org/xwiki/skin/test/ui
    • xwiki-platform-webjars

7 files changed

+135
-14
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
* See the NOTICE file distributed with this work for additional
3+
* information regarding copyright ownership.
4+
*
5+
* This is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU Lesser General Public License as
7+
* published by the Free Software Foundation; either version 2.1 of
8+
* the License, or (at your option) any later version.
9+
*
10+
* This software is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
* Lesser General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU Lesser General Public
16+
* License along with this software; if not, write to the Free
17+
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18+
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
19+
*/
20+
package org.xwiki.flamingo.test.docker;
21+
22+
import java.net.URI;
23+
24+
import org.apache.commons.httpclient.methods.GetMethod;
25+
import org.apache.commons.lang3.StringUtils;
26+
import org.junit.jupiter.api.Order;
27+
import org.junit.jupiter.api.Test;
28+
import org.xwiki.test.docker.junit5.UITest;
29+
import org.xwiki.test.ui.TestUtils;
30+
31+
import static org.junit.jupiter.api.Assertions.assertNotEquals;
32+
33+
/**
34+
* Tests related to the webjars endpoint.
35+
*
36+
* @version $Id$
37+
*/
38+
@UITest
39+
class WebJarsIT
40+
{
41+
@Test
42+
@Order(1)
43+
void pathTraversal(TestUtils setup) throws Exception
44+
{
45+
URI uri = new URI(StringUtils.removeEnd(setup.rest().getBaseURL(), "rest")
46+
+ "webjars/wiki%3Axwiki/..%2F..%2F..%2F..%2F..%2FWEB-INF%2Fxwiki.cfg");
47+
48+
GetMethod response = setup.rest().executeGet(uri);
49+
50+
assertNotEquals(200, response.getStatusCode());
51+
52+
response.releaseConnection();
53+
}
54+
}

xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/internal/template/InternalTemplateManager.java

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
import org.xwiki.cache.CacheException;
6060
import org.xwiki.cache.CacheManager;
6161
import org.xwiki.cache.config.LRUCacheConfiguration;
62+
import org.xwiki.classloader.internal.ClassLoaderUtils;
6263
import org.xwiki.component.annotation.Component;
6364
import org.xwiki.component.manager.ComponentLifecycleException;
6465
import org.xwiki.component.manager.ComponentLookupException;
@@ -1107,19 +1108,15 @@ private Template getClassloaderTemplate(String prefixPath, String templateName)
11071108

11081109
private Template getClassloaderTemplate(ClassLoader classloader, String prefixPath, String templateName)
11091110
{
1110-
String templatePath = prefixPath + templateName;
1111-
1112-
// Prevent access to resources from other directories
1113-
Path normalizedResource = Paths.get(templatePath).normalize();
1114-
// Protect against directory attacks.
1115-
if (!normalizedResource.startsWith(prefixPath)) {
1116-
this.logger.warn("Direct access to skin file [{}] refused. Possible break-in attempt!", normalizedResource);
1111+
URL url;
1112+
try {
1113+
url = ClassLoaderUtils.getResource(classloader, prefixPath, templateName);
1114+
} catch (IllegalArgumentException e) {
1115+
this.logger.warn("The template name [{}] is trying to execute a path traversal attack!", templateName);
11171116

11181117
return null;
11191118
}
11201119

1121-
URL url = classloader.getResource(templatePath);
1122-
11231120
return url != null ? new ClassloaderTemplate(new ClassloaderResource(url, templateName)) : null;
11241121
}
11251122

xwiki-platform-core/xwiki-platform-resource/xwiki-platform-resource-servlet/src/main/java/org/xwiki/resource/servlet/AbstractServletResourceReferenceHandler.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ public void handle(ResourceReference resourceReference, ResourceReferenceHandler
9292
sendError(HttpStatus.SC_NOT_FOUND, "Resource not found [%s].",
9393
getResourceName(typedResourceReference));
9494
}
95-
} catch (IOException | ResourceReferenceHandlerException e) {
95+
} catch (Exception e) {
9696
this.logger.error(e.getMessage(), e);
9797
sendError(HttpStatus.SC_INTERNAL_SERVER_ERROR, e.getMessage());
9898
}

xwiki-platform-core/xwiki-platform-skin/xwiki-platform-skin-skinx/src/main/java/com/xpn/xwiki/web/sx/SxResourceSource.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import java.nio.charset.StandardCharsets;
2525

2626
import org.apache.commons.io.IOUtils;
27+
import org.xwiki.classloader.internal.ClassLoaderUtils;
2728

2829
/**
2930
* JAR resource source for Skin Extensions.
@@ -58,7 +59,7 @@ public String getContent()
5859
try {
5960
// Load from the current context class loader to allow extensions to contribute skin extensions.
6061
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
61-
try (InputStream in = contextClassLoader.getResourceAsStream(this.resourceName)) {
62+
try (InputStream in = ClassLoaderUtils.getResourceAsStream(contextClassLoader, this.resourceName)) {
6263
return IOUtils.toString(in, StandardCharsets.UTF_8);
6364
}
6465
} catch (NullPointerException e) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* See the NOTICE file distributed with this work for additional
3+
* information regarding copyright ownership.
4+
*
5+
* This is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU Lesser General Public License as
7+
* published by the Free Software Foundation; either version 2.1 of
8+
* the License, or (at your option) any later version.
9+
*
10+
* This software is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
* Lesser General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU Lesser General Public
16+
* License along with this software; if not, write to the Free
17+
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18+
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
19+
*/
20+
package org.xwiki.skin.test.ui;
21+
22+
import java.net.URI;
23+
24+
import org.apache.commons.httpclient.methods.GetMethod;
25+
import org.junit.jupiter.api.Test;
26+
import org.xwiki.test.docker.junit5.UITest;
27+
import org.xwiki.test.ui.TestUtils;
28+
29+
import static org.junit.jupiter.api.Assertions.assertNotEquals;
30+
31+
/**
32+
* Verify the behavior of resource based skin resources.
33+
*
34+
* @version $Id$
35+
*/
36+
@UITest
37+
class SXSkinIT
38+
{
39+
@Test
40+
void pathTraversal(TestUtils setup) throws Exception
41+
{
42+
URI uri = new URI(setup.getURL("Main", "WebHome", "sx", "resource=../../WEB-INF/xwiki.cfg"));
43+
44+
GetMethod response = setup.rest().executeGet(uri);
45+
46+
assertNotEquals(200, response.getStatusCode());
47+
48+
response.releaseConnection();
49+
}
50+
}

xwiki-platform-core/xwiki-platform-webjars/xwiki-platform-webjars-api/src/main/java/org/xwiki/webjars/internal/WebJarsResourceReferenceHandler.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030

3131
import org.apache.tika.mime.MediaType;
3232
import org.xwiki.classloader.ClassLoaderManager;
33+
import org.xwiki.classloader.internal.ClassLoaderUtils;
3334
import org.xwiki.component.annotation.Component;
3435
import org.xwiki.resource.ResourceReferenceHandlerException;
3536
import org.xwiki.resource.ResourceType;
@@ -76,8 +77,8 @@ public List<ResourceType> getSupportedResourceReferences()
7677
@Override
7778
protected InputStream getResourceStream(WebJarsResourceReference resourceReference)
7879
{
79-
String resourcePath = String.format("%s%s", WEBJARS_RESOURCE_PREFIX, getResourceName(resourceReference));
80-
return getClassLoader(resourceReference.getNamespace()).getResourceAsStream(resourcePath);
80+
return ClassLoaderUtils.getResourceAsStream(getClassLoader(resourceReference.getNamespace()),
81+
WEBJARS_RESOURCE_PREFIX, getResourceName(resourceReference));
8182
}
8283

8384
@Override

xwiki-platform-core/xwiki-platform-webjars/xwiki-platform-webjars-test/xwiki-platform-webjars-test-tests/src/test/it/org/xwiki/webjars/test/ui/WebJarsTest.java

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@
1919
*/
2020
package org.xwiki.webjars.test.ui;
2121

22+
import java.net.URI;
23+
24+
import org.apache.commons.httpclient.methods.GetMethod;
25+
import org.apache.commons.lang3.StringUtils;
2226
import org.junit.Rule;
2327
import org.junit.Test;
2428
import org.openqa.selenium.By;
@@ -27,7 +31,8 @@
2731
import org.xwiki.test.ui.SuperAdminAuthenticationRule;
2832
import org.xwiki.test.ui.po.ViewPage;
2933

30-
import static org.junit.Assert.*;
34+
import static org.junit.Assert.assertTrue;
35+
import static org.junit.Assert.assertNotEquals;
3136

3237
/**
3338
* Functional tests for the WebJars integration.
@@ -73,4 +78,17 @@ public void testWebJars() throws Exception
7378
// Verify that the served resource is the one from the webjars
7479
assertTrue(getDriver().getPageSource().contains("// AjaxQ jQuery Plugin"));
7580
}
81+
82+
@Test
83+
public void pathTraversal() throws Exception
84+
{
85+
URI uri = new URI(StringUtils.removeEnd(getUtil().rest().getBaseURL(), "rest")
86+
+ "webjars/wiki%3Axwiki/..%2F..%2F..%2F..%2F..%2FWEB-INF%2Fxwiki.cfg");
87+
88+
GetMethod response = getUtil().rest().executeGet(uri);
89+
90+
assertNotEquals(200, response.getStatusCode());
91+
92+
response.releaseConnection();
93+
}
7694
}

0 commit comments

Comments
 (0)