Improved TryFilesFilter to use built-in Servlet API methods to

retrieve the files, in order to avoid filesystem vulnerabilities.
This commit is contained in:
Simone Bordet 2013-11-05 09:05:52 +01:00
parent 226c522451
commit 2228b4e03b
2 changed files with 30 additions and 25 deletions

View File

@ -19,6 +19,8 @@
package org.eclipse.jetty.fcgi.proxy; package org.eclipse.jetty.fcgi.proxy;
import java.io.IOException; import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
@ -39,26 +41,17 @@ public class TryFilesFilter implements Filter
public static final String ROOT_INIT_PARAM = "root"; public static final String ROOT_INIT_PARAM = "root";
public static final String FILES_INIT_PARAM = "files"; public static final String FILES_INIT_PARAM = "files";
private String root;
private String[] files; private String[] files;
@Override @Override
public void init(FilterConfig config) throws ServletException public void init(FilterConfig config) throws ServletException
{ {
root = config.getInitParameter(ROOT_INIT_PARAM);
if (root == null)
throw new ServletException(String.format("Missing mandatory parameter '%s'", ROOT_INIT_PARAM));
String param = config.getInitParameter(FILES_INIT_PARAM); String param = config.getInitParameter(FILES_INIT_PARAM);
if (param == null) if (param == null)
throw new ServletException(String.format("Missing mandatory parameter '%s'", FILES_INIT_PARAM)); throw new ServletException(String.format("Missing mandatory parameter '%s'", FILES_INIT_PARAM));
files = param.split(" "); files = param.split(" ");
} }
public String getRoot()
{
return root;
}
@Override @Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
{ {
@ -69,8 +62,12 @@ public class TryFilesFilter implements Filter
{ {
String file = files[i]; String file = files[i];
String resolved = resolve(httpRequest, file); String resolved = resolve(httpRequest, file);
Path path = Paths.get(getRoot(), resolved);
if (Files.exists(path) && Files.isReadable(path)) URL url = request.getServletContext().getResource(resolved);
if (url == null)
continue;
if (Files.isReadable(toPath(url)))
{ {
chain.doFilter(httpRequest, httpResponse); chain.doFilter(httpRequest, httpResponse);
return; return;
@ -81,25 +78,33 @@ public class TryFilesFilter implements Filter
fallback(httpRequest, httpResponse, chain, files[files.length - 1]); fallback(httpRequest, httpResponse, chain, files[files.length - 1]);
} }
private Path toPath(URL url) throws IOException
{
try
{
return Paths.get(url.toURI());
}
catch (URISyntaxException x)
{
throw new IOException(x);
}
}
protected void fallback(HttpServletRequest request, HttpServletResponse response, FilterChain chain, String fallback) throws IOException, ServletException protected void fallback(HttpServletRequest request, HttpServletResponse response, FilterChain chain, String fallback) throws IOException, ServletException
{ {
String resolved = resolve(request, fallback); String resolved = resolve(request, fallback);
request.getRequestDispatcher(resolved).forward(request, response); request.getServletContext().getRequestDispatcher(resolved).forward(request, response);
} }
private String resolve(HttpServletRequest request, String value) private String resolve(HttpServletRequest request, String value)
{ {
String path = request.getRequestURI(); String path = request.getServletPath();
String query = request.getQueryString(); String info = request.getPathInfo();
if (info != null)
String result = value.replaceAll("\\$path", path); path += info;
result = result.replaceAll("\\$query", query == null ? "" : query); if (!path.startsWith("/"))
path = "/" + path;
// Remove the "?" or "&" at the end if there is no query return value.replaceAll("\\$path", path);
if (query == null && (result.endsWith("?") || result.endsWith("&")))
result = result.substring(0, result.length() - 1);
return result;
} }
@Override @Override

View File

@ -70,8 +70,8 @@ public class WordPressSPDYFastCGIProxyServer
FilterHolder tryFileFilter = context.addFilter(TryFilesFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST)); FilterHolder tryFileFilter = context.addFilter(TryFilesFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST));
tryFileFilter.setInitParameter(TryFilesFilter.ROOT_INIT_PARAM, root); tryFileFilter.setInitParameter(TryFilesFilter.ROOT_INIT_PARAM, root);
// tryFileFilter.setInitParameter(TryFilesFilter.FILES_INIT_PARAM, "$path $path/index.php?$query"); // Permalink /?p=123 // tryFileFilter.setInitParameter(TryFilesFilter.FILES_INIT_PARAM, "$path $path/index.php"); // Permalink /?p=123
tryFileFilter.setInitParameter(TryFilesFilter.FILES_INIT_PARAM, "$path /index.php?p=$path&$query"); // Permalink /%year%/%monthnum%/%postname% tryFileFilter.setInitParameter(TryFilesFilter.FILES_INIT_PARAM, "$path /index.php?p=$path"); // Permalink /%year%/%monthnum%/%postname%
// FastCGI // FastCGI
ServletHolder fcgiServlet = new ServletHolder(FastCGIProxyServlet.class); ServletHolder fcgiServlet = new ServletHolder(FastCGIProxyServlet.class);