diff options
author | Tatu Lund <tatu@vaadin.com> | 2019-11-19 14:31:18 +0200 |
---|---|---|
committer | Anna Koskinen <Ansku@users.noreply.github.com> | 2019-11-19 14:31:18 +0200 |
commit | ce497adfbdb6875e3cbe783cfc280999a9ae04d9 (patch) | |
tree | 40796b5eda810a6e86c914890b7fcf9eddfcf5c1 | |
parent | c20e2e9c1aefb99eae2bd69df02e1324c7abe479 (diff) | |
download | vaadin-framework-ce497adfbdb6875e3cbe783cfc280999a9ae04d9.tar.gz vaadin-framework-ce497adfbdb6875e3cbe783cfc280999a9ae04d9.zip |
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.
-rw-r--r-- | server/src/main/java/com/vaadin/server/VaadinServlet.java | 29 | ||||
-rw-r--r-- | server/src/test/java/com/vaadin/server/VaadinServletTest.java | 2 |
2 files changed, 26 insertions, 5 deletions
diff --git a/server/src/main/java/com/vaadin/server/VaadinServlet.java b/server/src/main/java/com/vaadin/server/VaadinServlet.java index b0d270accb..e7e57a1278 100644 --- a/server/src/main/java/com/vaadin/server/VaadinServlet.java +++ b/server/src/main/java/com/vaadin/server/VaadinServlet.java @@ -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; diff --git a/server/src/test/java/com/vaadin/server/VaadinServletTest.java b/server/src/test/java/com/vaadin/server/VaadinServletTest.java index f1490208d4..652dc30665 100644 --- a/server/src/test/java/com/vaadin/server/VaadinServletTest.java +++ b/server/src/test/java/com/vaadin/server/VaadinServletTest.java @@ -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; } } |