diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/filedownload/FileDownloadAction.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/filedownload/FileDownloadAction.java index 4dd1be5f5..c9fab7f46 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/filedownload/FileDownloadAction.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/filedownload/FileDownloadAction.java @@ -39,7 +39,23 @@ public class FileDownloadAction implements Action { } public void setInputPath(String value) { - inputPath = value; + inputPath = sanitizeInputPath(value); + } + + /** + * As the user modifiable parameter inputPath will be used to access server side resources, we want the path to be + * sanitized - in this case it is demonstrated to disallow inputPath parameter values containing "WEB-INF". Consider to + * use even stricter rules in production environments. + * + * @param value the raw parameter input value to sanitize + * + * @return the sanitized value; null if value contains an invalid path segment like WEB-INF + */ + String sanitizeInputPath( String value ) { + if (value != null && value.toUpperCase().contains("WEB-INF")) { + return null; + } + return value; } public InputStream getInputStream() throws Exception { diff --git a/apps/showcase/src/test/java/org/apache/struts2/showcase/filedownload/FileDownloadActionTest.java b/apps/showcase/src/test/java/org/apache/struts2/showcase/filedownload/FileDownloadActionTest.java new file mode 100644 index 000000000..cf8fbe3bc --- /dev/null +++ b/apps/showcase/src/test/java/org/apache/struts2/showcase/filedownload/FileDownloadActionTest.java @@ -0,0 +1,42 @@ +package org.apache.struts2.showcase.filedownload; + +import org.junit.Before; +import org.junit.Test; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertNull; + +public class FileDownloadActionTest { + + private FileDownloadAction fileDownloadAction; + + @Before + public void setUp() { + this.fileDownloadAction = new FileDownloadAction(); + } + + @Test + public void testSanitizeInputPathShouldAllowSimpleParameter() throws Exception { + assertEquals("foo", fileDownloadAction.sanitizeInputPath("foo")); + } + + @Test + public void testSanitizeInputPathShouldReturnNullForNullInput() throws Exception { + assertNull(fileDownloadAction.sanitizeInputPath(null)); + } + + @Test + public void testSanitizeInputPathShouldReturnNullForLeadingWebInf() throws Exception { + assertNull(fileDownloadAction.sanitizeInputPath("WEB-INF/foo")); + } + + @Test + public void testSanitizeInputPathShouldReturnNullForNonLeadingWebInf() throws Exception { + assertNull(fileDownloadAction.sanitizeInputPath("./WEB-INF/foo")); + } + + @Test + public void testSanitizeInputPathShouldReturnNullForNonUppercaseWebInf() throws Exception { + assertNull(fileDownloadAction.sanitizeInputPath("./wEB-Inf/foo")); + } +}