hbase-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From els...@apache.org
Subject [4/5] hbase git commit: HBASE-17409 Limit jsonp callback name to prevent xss
Date Thu, 05 Jan 2017 01:03:47 GMT
HBASE-17409 Limit jsonp callback name to prevent xss


Project: http://git-wip-us.apache.org/repos/asf/hbase/repo
Commit: http://git-wip-us.apache.org/repos/asf/hbase/commit/601518ab
Tree: http://git-wip-us.apache.org/repos/asf/hbase/tree/601518ab
Diff: http://git-wip-us.apache.org/repos/asf/hbase/diff/601518ab

Branch: refs/heads/branch-1.2
Commit: 601518abbf6623bcc6ba28e41b8936372bd6afaa
Parents: 28ec260
Author: Josh Elser <elserj@apache.org>
Authored: Tue Jan 3 17:46:45 2017 -0500
Committer: Josh Elser <elserj@apache.org>
Committed: Wed Jan 4 19:36:55 2017 -0500

----------------------------------------------------------------------
 .../hadoop/hbase/http/jmx/JMXJsonServlet.java   | 29 ++++++++++++++++----
 .../hbase/http/jmx/TestJMXJsonServlet.java      | 25 +++++++++++++++++
 2 files changed, 48 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/hbase/blob/601518ab/hbase-server/src/main/java/org/apache/hadoop/hbase/http/jmx/JMXJsonServlet.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/http/jmx/JMXJsonServlet.java
b/hbase-server/src/main/java/org/apache/hadoop/hbase/http/jmx/JMXJsonServlet.java
index 8ba26dd..0d7d99a 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/http/jmx/JMXJsonServlet.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/http/jmx/JMXJsonServlet.java
@@ -152,9 +152,7 @@ public class JMXJsonServlet extends HttpServlet {
    *          The servlet response we are creating
    */
   @Override
-  @edu.umd.cs.findbugs.annotations.SuppressWarnings(value="XSS_REQUEST_PARAMETER_TO_SERVLET_WRITER",
-    justification="TODO: See HBASE-15122")
-  public void doGet(HttpServletRequest request, HttpServletResponse response) {
+  public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException
{
     try {
       if (!HttpServer.isInstrumentationAccessAllowed(getServletContext(), request, response))
{
         return;
@@ -163,10 +161,10 @@ public class JMXJsonServlet extends HttpServlet {
       PrintWriter writer = null;
       JSONBean.Writer beanWriter = null;
       try {
+        jsonpcb = checkCallbackName(request.getParameter(CALLBACK_PARAM));
         writer = response.getWriter();
         beanWriter = this.jsonBeanWriter.open(writer);
         // "callback" parameter implies JSONP outpout
-        jsonpcb = request.getParameter(CALLBACK_PARAM);
         if (jsonpcb != null) {
           response.setContentType("application/javascript; charset=utf8");
           writer.write(jsonpcb + "(");
@@ -216,10 +214,29 @@ public class JMXJsonServlet extends HttpServlet {
       }
     } catch (IOException e) {
       LOG.error("Caught an exception while processing JMX request", e);
-      response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+      response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
     } catch (MalformedObjectNameException e) {
       LOG.error("Caught an exception while processing JMX request", e);
-      response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
+      response.sendError(HttpServletResponse.SC_BAD_REQUEST);
     }
   }
+
+  /**
+   * Verifies that the callback property, if provided, is purely alphanumeric.
+   * This prevents a malicious callback name (that is javascript code) from being
+   * returned by the UI to an unsuspecting user.
+   *
+   * @param callbackName The callback name, can be null.
+   * @return The callback name
+   * @throws IOException If the name is disallowed.
+   */
+  private String checkCallbackName(String callbackName) throws IOException {
+    if (null == callbackName) {
+      return null;
+    }
+    if (callbackName.matches("[A-Za-z0-9_]+")) {
+      return callbackName;
+    }
+    throw new IOException("'callback' must be alphanumeric");
+  }
 }

http://git-wip-us.apache.org/repos/asf/hbase/blob/601518ab/hbase-server/src/test/java/org/apache/hadoop/hbase/http/jmx/TestJMXJsonServlet.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/http/jmx/TestJMXJsonServlet.java
b/hbase-server/src/test/java/org/apache/hadoop/hbase/http/jmx/TestJMXJsonServlet.java
index dd345fb..5e02a78 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/http/jmx/TestJMXJsonServlet.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/http/jmx/TestJMXJsonServlet.java
@@ -17,10 +17,14 @@
 
 package org.apache.hadoop.hbase.http.jmx;
 
+import java.net.HttpURLConnection;
 import java.net.URL;
+import java.net.URLEncoder;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
+import javax.servlet.http.HttpServletResponse;
+
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.hadoop.hbase.testclassification.SmallTests;
@@ -38,6 +42,9 @@ public class TestJMXJsonServlet extends HttpServerFunctionalTest {
   private static URL baseUrl;
 
   @BeforeClass public static void setup() throws Exception {
+    // Eclipse doesn't pick this up correctly from the plugin
+    // configuration in the pom.
+    System.setProperty(HttpServerFunctionalTest.TEST_BUILD_WEBAPPS, "target/test-classes/webapps");
     server = createTestServer();
     server.start();
     baseUrl = getServerURL(server);
@@ -105,4 +112,22 @@ public class TestJMXJsonServlet extends HttpServerFunctionalTest {
     assertReFind("\\}\\);$", result);
 
   }
+
+  @Test
+  public void testDisallowedJSONPCallback() throws Exception {
+    String callback = "function(){alert('bigproblems!')};foo";
+    URL url = new URL(
+        baseUrl, "/jmx?qry=java.lang:type=Memory&callback="+URLEncoder.encode(callback,
"UTF-8"));
+    HttpURLConnection cnxn = (HttpURLConnection) url.openConnection();
+    assertEquals(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, cnxn.getResponseCode());
+  }
+
+  @Test
+  public void testUnderscoresInJSONPCallback() throws Exception {
+    String callback = "my_function";
+    URL url = new URL(
+        baseUrl, "/jmx?qry=java.lang:type=Memory&callback="+URLEncoder.encode(callback,
"UTF-8"));
+    HttpURLConnection cnxn = (HttpURLConnection) url.openConnection();
+    assertEquals(HttpServletResponse.SC_OK, cnxn.getResponseCode());
+  }
 }


Mime
View raw message