diff --git a/tez-common/src/main/java/org/apache/tez/common/web/ProfileOutputServlet.java b/tez-common/src/main/java/org/apache/tez/common/web/ProfileOutputServlet.java index b95d878529..e1b9d2f058 100644 --- a/tez-common/src/main/java/org/apache/tez/common/web/ProfileOutputServlet.java +++ b/tez-common/src/main/java/org/apache/tez/common/web/ProfileOutputServlet.java @@ -21,6 +21,7 @@ import java.io.IOException; import java.io.PrintWriter; import java.nio.file.Files; +import java.nio.file.Path; import java.nio.file.Paths; import javax.servlet.ServletException; @@ -43,7 +44,16 @@ public void doGet(HttpServletRequest request, HttpServletResponse response) thro writeMessage(response, "Run the profiler to be able to receive its output"); return; } - File outputFile = new File(ProfileServlet.OUTPUT_DIR, queriedFile); + Path outputDir = Paths.get(ProfileServlet.OUTPUT_DIR).toAbsolutePath().normalize(); + Path requestedPath = outputDir.resolve(queriedFile).normalize(); + + if (!requestedPath.startsWith(outputDir)) { + response.setStatus(HttpServletResponse.SC_FORBIDDEN); + writeMessage(response, "Access denied: Invalid Path"); + return; + } + File outputFile = requestedPath.toFile(); + if (!outputFile.exists()) { writeMessage(response, "Requested file does not exist: " + queriedFile); return; diff --git a/tez-tests/src/test/java/org/apache/tez/test/TestAM.java b/tez-tests/src/test/java/org/apache/tez/test/TestAM.java index 3338deb3d9..adfe18a9eb 100644 --- a/tez-tests/src/test/java/org/apache/tez/test/TestAM.java +++ b/tez-tests/src/test/java/org/apache/tez/test/TestAM.java @@ -17,6 +17,7 @@ */ package org.apache.tez.test; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; @@ -25,6 +26,8 @@ import java.net.HttpURLConnection; import java.net.URL; +import javax.servlet.http.HttpServletResponse; + import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.conf.Configuration.IntegerRanges; import org.apache.hadoop.fs.FileSystem; @@ -133,6 +136,12 @@ public void testAMWebUIService() throws TezException, IOException, InterruptedEx checkAddress(webUIAddress + "/prof", 202); checkAddress(webUIAddress + "/prof-output"); + HttpURLConnection connection = + (HttpURLConnection) new URL(webUIAddress + "/prof-output?file=../etc/web").openConnection(); + connection.connect(); + assertEquals(HttpServletResponse.SC_FORBIDDEN, connection.getResponseCode()); + assertTrue(new String(connection.getErrorStream().readAllBytes()).contains("Access denied: Invalid Path")); + URL url = new URL(webUIAddress); IntegerRanges portRange = conf.getRange(TezConfiguration.TEZ_AM_WEBSERVICE_PORT_RANGE, TezConfiguration.TEZ_AM_WEBSERVICE_PORT_RANGE_DEFAULT);