SWF-706 - ResourceServlet allows HTTP access to sensitive files
This commit is contained in:
@@ -30,7 +30,6 @@ import java.util.zip.GZIPOutputStream;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
@@ -38,13 +37,14 @@ import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.servlet.HttpServletBean;
|
||||
|
||||
/**
|
||||
* Special resource servlet for efficiently resolving and rendering static resources from within a JAR file.
|
||||
*
|
||||
* @author Jeremy Grelle
|
||||
*/
|
||||
public class ResourceServlet extends HttpServlet {
|
||||
public class ResourceServlet extends HttpServletBean {
|
||||
|
||||
private static final String HTTP_CONTENT_LENGTH_HEADER = "Content-Length";
|
||||
|
||||
@@ -54,14 +54,16 @@ public class ResourceServlet extends HttpServlet {
|
||||
|
||||
private static final String HTTP_CACHE_CONTROL_HEADER = "Cache-Control";
|
||||
|
||||
private static final String GZIP_ENABLED_PARAM = "gzipEnabled";
|
||||
|
||||
private static final Log log = LogFactory.getLog(ResourceServlet.class);
|
||||
|
||||
private final String protectedPath = "/?WEB-INF/.*";
|
||||
|
||||
private boolean gzipEnabled = true;
|
||||
|
||||
private String[] allowedResourcePaths = new String[] { "/**/*.css", "/**/*.gif", "/**/*.ico", "/**/*.jpeg",
|
||||
"/**/*.jpg", "/**/*.js", "/**/*.png", "META-INF/**/*.css", "META-INF/**/*.gif", "META-INF/**/*.ico",
|
||||
"META-INF/**/*.jpeg", "META-INF/**/*.jpg", "META-INF/**/*.js", "META-INF/**/*.png" };
|
||||
|
||||
private Map defaultMimeTypes = new HashMap();
|
||||
{
|
||||
defaultMimeTypes.put(".css", "text/css");
|
||||
@@ -79,13 +81,6 @@ public class ResourceServlet extends HttpServlet {
|
||||
compressedMimeTypes.add("text/javascript");
|
||||
}
|
||||
|
||||
public void init() throws ServletException {
|
||||
String gzipEnabledParamValue = getServletConfig().getInitParameter(GZIP_ENABLED_PARAM);
|
||||
if (StringUtils.hasText(gzipEnabledParamValue)) {
|
||||
gzipEnabled = Boolean.valueOf(gzipEnabledParamValue).booleanValue();
|
||||
}
|
||||
}
|
||||
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
||||
|
||||
String rawResourcePath = request.getPathInfo();
|
||||
@@ -215,7 +210,7 @@ public class ResourceServlet extends HttpServlet {
|
||||
URL[] resources = new URL[localResourcePaths.length];
|
||||
for (int i = 0; i < localResourcePaths.length; i++) {
|
||||
String localResourcePath = localResourcePaths[i];
|
||||
if (localResourcePath.matches(protectedPath)) {
|
||||
if (!isAllowed(localResourcePath)) {
|
||||
if (log.isWarnEnabled()) {
|
||||
log.warn("An attempt to access a protected resource at " + localResourcePath + " was disallowed.");
|
||||
}
|
||||
@@ -224,6 +219,14 @@ public class ResourceServlet extends HttpServlet {
|
||||
URL resource = getServletContext().getResource(localResourcePath);
|
||||
if (resource == null) {
|
||||
String jarResourcePath = "META-INF" + localResourcePath;
|
||||
if (!isAllowed(jarResourcePath)) {
|
||||
if (log.isWarnEnabled()) {
|
||||
log
|
||||
.warn("An attempt to access a protected resource at " + jarResourcePath
|
||||
+ " was disallowed.");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Searching classpath for resource: " + jarResourcePath);
|
||||
}
|
||||
@@ -241,6 +244,18 @@ public class ResourceServlet extends HttpServlet {
|
||||
return resources;
|
||||
}
|
||||
|
||||
private boolean isAllowed(String resourcePath) {
|
||||
if (resourcePath.matches(protectedPath)) {
|
||||
return false;
|
||||
}
|
||||
/*
|
||||
* PathMatcher pathMatcher = new AntPathMatcher(); for (int i = 0; i < allowedResourcePaths.length; i++) {
|
||||
* String pattern = allowedResourcePaths[i]; if (pathMatcher.match(pattern, resourcePath)) { return true; } }
|
||||
* return false;
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set HTTP headers to allow caching for the given number of seconds.
|
||||
* @param seconds number of seconds into the future that the response should be cacheable for
|
||||
@@ -322,4 +337,12 @@ public class ResourceServlet extends HttpServlet {
|
||||
// noop
|
||||
}
|
||||
}
|
||||
|
||||
public void setGzipEnabled(boolean gzipEnabled) {
|
||||
this.gzipEnabled = gzipEnabled;
|
||||
}
|
||||
|
||||
public void setAllowedResourcePaths(String[] allowedResourcePaths) {
|
||||
this.allowedResourcePaths = allowedResourcePaths;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user