Browse Source

Decode path in getStaticFilePath (#11812)

* Decode path in getStaticFilePath

Some containers do not decode path when using getPathInfo, in case path has not been decoded there is a risk for path traversal vulnerability.
tags/8.10.0.alpha1
Tatu Lund 4 years ago
parent
commit
ce497adfbd

+ 24
- 5
server/src/main/java/com/vaadin/server/VaadinServlet.java View File

@@ -28,11 +28,13 @@ import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLDecoder;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
@@ -1348,16 +1350,33 @@ public class VaadinServlet extends HttpServlet implements Constants {
* @since 8.0
*/
protected String getStaticFilePath(HttpServletRequest request) {
String pathInfo = request.getPathInfo();
if (pathInfo == null) {
if (request.getPathInfo() == null) {
return null;
}
String decodedPath = null;
String contextPath = null;
try {
// pathInfo should be already decoded, but some containers do not decode it,
// hence we use getRequestURI instead.
decodedPath = URLDecoder.decode(request.getRequestURI(), StandardCharsets.UTF_8.name());
contextPath = URLDecoder.decode(request.getContextPath(), StandardCharsets.UTF_8.name());
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("An error occurred during decoding URL.",e);
}
// Possible context path needs to be removed
String filePath = decodedPath.substring(contextPath.length());
String servletPath = request.getServletPath();
// Possible servlet path needs to be removed
if (!servletPath.isEmpty() && !servletPath.equals("/VAADIN")
&& filePath.startsWith(servletPath)) {
filePath = filePath.substring(servletPath.length());
}
// Servlet mapped as /* serves at /VAADIN
// Servlet mapped as /foo/bar/* serves at /foo/bar/VAADIN
if (pathInfo.startsWith("/VAADIN/")) {
return pathInfo;
if (filePath.startsWith("/VAADIN/")) {
return filePath;
}
String servletPrefixedPath = request.getServletPath() + pathInfo;
String servletPrefixedPath = servletPath + filePath;
// Servlet mapped as /VAADIN/*
if (servletPrefixedPath.startsWith("/VAADIN/")) {
return servletPrefixedPath;

+ 2
- 0
server/src/test/java/com/vaadin/server/VaadinServletTest.java View File

@@ -116,6 +116,8 @@ public class VaadinServletTest {
HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
Mockito.when(request.getServletPath()).thenReturn(servletPath);
Mockito.when(request.getPathInfo()).thenReturn(pathInfo);
Mockito.when(request.getRequestURI()).thenReturn("/context"+pathInfo);
Mockito.when(request.getContextPath()).thenReturn("/context");
return request;
}
}

Loading…
Cancel
Save