From 41b9a461df287e4793eb722671bc3a75b65ebf25 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Mon, 25 Jul 2011 10:57:39 +0000 Subject: [PATCH] ResourceHttpRequestHandler detects invalid directory traversal in given path (SPR-8515) --- .../resource/ResourceHttpRequestHandler.java | 17 ++++++++++++--- .../ResourceHttpRequestHandlerTests.java | 21 +++++++++++++++++-- 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/resource/ResourceHttpRequestHandler.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/resource/ResourceHttpRequestHandler.java index 8540de9c2e0..47298400c60 100644 --- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/resource/ResourceHttpRequestHandler.java +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/resource/ResourceHttpRequestHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2010 the original author or authors. + * Copyright 2002-2011 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -75,7 +75,7 @@ public class ResourceHttpRequestHandler extends WebContentGenerator implements H * for serving static resources. */ public void setLocations(List locations) { - Assert.notEmpty(locations, "Location list must not be empty"); + Assert.notEmpty(locations, "Locations list must not be empty"); this.locations = locations; } @@ -142,7 +142,7 @@ public class ResourceHttpRequestHandler extends WebContentGenerator implements H HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE + "' is not set"); } - if (!StringUtils.hasText(path) || path.contains("WEB-INF") || path.contains("META-INF")) { + if (!StringUtils.hasText(path) || isInvalidPath(path)) { if (logger.isDebugEnabled()) { logger.debug("Ignoring invalid resource path [" + path + "]"); } @@ -172,6 +172,17 @@ public class ResourceHttpRequestHandler extends WebContentGenerator implements H return null; } + /** + * Validates the given path: returns {@code true} if the given path is not a valid resource path. + *

The default implementation rejects paths containing "WEB-INF" or "META-INF" as well as paths + * with relative paths ("../") that result in access of a parent directory. + * @param path the path to validate + * @return {@code true} if the path has been recognized as invalid, {@code false} otherwise + */ + protected boolean isInvalidPath(String path) { + return (path.contains("WEB-INF") || path.contains("META-INF") || StringUtils.cleanPath(path).startsWith("..")); + } + /** * Determine an appropriate media type for the given resource. * @param resource the resource to check diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/resource/ResourceHttpRequestHandlerTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/resource/ResourceHttpRequestHandlerTests.java index 1ac0ff2c25b..d6a5f42fd6a 100644 --- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/resource/ResourceHttpRequestHandlerTests.java +++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/resource/ResourceHttpRequestHandlerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2010 the original author or authors. + * Copyright 2002-2011 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,7 +20,6 @@ import java.util.ArrayList; import java.util.List; import javax.servlet.http.HttpServletResponse; -import static org.junit.Assert.*; import org.junit.Before; import org.junit.Test; @@ -32,6 +31,8 @@ import org.springframework.mock.web.MockServletContext; import org.springframework.web.HttpRequestMethodNotSupportedException; import org.springframework.web.servlet.HandlerMapping; +import static org.junit.Assert.*; + /** * @author Keith Donald * @author Jeremy Grelle @@ -119,6 +120,22 @@ public class ResourceHttpRequestHandlerTests { assertEquals("function foo() { console.log(\"hello world\"); }", response.getContentAsString()); } + @Test + public void getResourceViaDirectoryTraversal() throws Exception { + MockHttpServletRequest request = new MockHttpServletRequest(); + request.setMethod("GET"); + + request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "../testsecret/secret.txt"); + MockHttpServletResponse response = new MockHttpServletResponse(); + handler.handleRequest(request, response); + assertEquals(404, response.getStatus()); + + request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "test/../../testsecret/secret.txt"); + response = new MockHttpServletResponse(); + handler.handleRequest(request, response); + assertEquals(404, response.getStatus()); + } + @Test public void notModified() throws Exception { MockHttpServletRequest request = new MockHttpServletRequest();