Skip to content

Commit 41b9a46

Browse files
committed
ResourceHttpRequestHandler detects invalid directory traversal in given path (SPR-8515)
1 parent 037497c commit 41b9a46

File tree

2 files changed

+33
-5
lines changed

2 files changed

+33
-5
lines changed

org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/resource/ResourceHttpRequestHandler.java

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2010 the original author or authors.
2+
* Copyright 2002-2011 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -75,7 +75,7 @@ public ResourceHttpRequestHandler() {
7575
* for serving static resources.
7676
*/
7777
public void setLocations(List<Resource> locations) {
78-
Assert.notEmpty(locations, "Location list must not be empty");
78+
Assert.notEmpty(locations, "Locations list must not be empty");
7979
this.locations = locations;
8080
}
8181

@@ -142,7 +142,7 @@ protected Resource getResource(HttpServletRequest request) {
142142
HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE + "' is not set");
143143
}
144144

145-
if (!StringUtils.hasText(path) || path.contains("WEB-INF") || path.contains("META-INF")) {
145+
if (!StringUtils.hasText(path) || isInvalidPath(path)) {
146146
if (logger.isDebugEnabled()) {
147147
logger.debug("Ignoring invalid resource path [" + path + "]");
148148
}
@@ -172,6 +172,17 @@ else if (logger.isTraceEnabled()) {
172172
return null;
173173
}
174174

175+
/**
176+
* Validates the given path: returns {@code true} if the given path is not a valid resource path.
177+
* <p>The default implementation rejects paths containing "WEB-INF" or "META-INF" as well as paths
178+
* with relative paths ("../") that result in access of a parent directory.
179+
* @param path the path to validate
180+
* @return {@code true} if the path has been recognized as invalid, {@code false} otherwise
181+
*/
182+
protected boolean isInvalidPath(String path) {
183+
return (path.contains("WEB-INF") || path.contains("META-INF") || StringUtils.cleanPath(path).startsWith(".."));
184+
}
185+
175186
/**
176187
* Determine an appropriate media type for the given resource.
177188
* @param resource the resource to check

org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/resource/ResourceHttpRequestHandlerTests.java

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2010 the original author or authors.
2+
* Copyright 2002-2011 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -20,7 +20,6 @@
2020
import java.util.List;
2121
import javax.servlet.http.HttpServletResponse;
2222

23-
import static org.junit.Assert.*;
2423
import org.junit.Before;
2524
import org.junit.Test;
2625

@@ -32,6 +31,8 @@
3231
import org.springframework.web.HttpRequestMethodNotSupportedException;
3332
import org.springframework.web.servlet.HandlerMapping;
3433

34+
import static org.junit.Assert.*;
35+
3536
/**
3637
* @author Keith Donald
3738
* @author Jeremy Grelle
@@ -119,6 +120,22 @@ public void getResourceFromSubDirectoryOfAlternatePath() throws Exception {
119120
assertEquals("function foo() { console.log(\"hello world\"); }", response.getContentAsString());
120121
}
121122

123+
@Test
124+
public void getResourceViaDirectoryTraversal() throws Exception {
125+
MockHttpServletRequest request = new MockHttpServletRequest();
126+
request.setMethod("GET");
127+
128+
request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "../testsecret/secret.txt");
129+
MockHttpServletResponse response = new MockHttpServletResponse();
130+
handler.handleRequest(request, response);
131+
assertEquals(404, response.getStatus());
132+
133+
request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "test/../../testsecret/secret.txt");
134+
response = new MockHttpServletResponse();
135+
handler.handleRequest(request, response);
136+
assertEquals(404, response.getStatus());
137+
}
138+
122139
@Test
123140
public void notModified() throws Exception {
124141
MockHttpServletRequest request = new MockHttpServletRequest();

0 commit comments

Comments
 (0)