You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by el...@apache.org on 2017/01/05 01:03:44 UTC
[1/5] hbase git commit: HBASE-17409 Limit jsonp callback name to
prevent xss
Repository: hbase
Updated Branches:
refs/heads/branch-1 36f16bbe1 -> 4dcb07f99
refs/heads/branch-1.1 e32f8ac42 -> 63d8186d4
refs/heads/branch-1.2 28ec26035 -> 601518abb
refs/heads/branch-1.3 e359c76e8 -> 1829cd541
refs/heads/master 63bd8be57 -> 20a7ae286
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/20a7ae28
Tree: http://git-wip-us.apache.org/repos/asf/hbase/tree/20a7ae28
Diff: http://git-wip-us.apache.org/repos/asf/hbase/diff/20a7ae28
Branch: refs/heads/master
Commit: 20a7ae28657c41027486f7d2c8e1b260b692f418
Parents: 63bd8be
Author: Josh Elser <el...@apache.org>
Authored: Tue Jan 3 17:46:45 2017 -0500
Committer: Josh Elser <el...@apache.org>
Committed: Wed Jan 4 17:05:07 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/20a7ae28/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 45c2c15..3abad3a 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
@@ -149,9 +149,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;
@@ -160,11 +158,11 @@ 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 + "(");
@@ -214,10 +212,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/20a7ae28/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 031ddce..d7e68d5 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.MiscTests;
@@ -39,6 +43,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);
@@ -106,4 +113,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());
+ }
}
[2/5] hbase git commit: HBASE-17409 Limit jsonp callback name to
prevent xss
Posted by el...@apache.org.
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/4dcb07f9
Tree: http://git-wip-us.apache.org/repos/asf/hbase/tree/4dcb07f9
Diff: http://git-wip-us.apache.org/repos/asf/hbase/diff/4dcb07f9
Branch: refs/heads/branch-1
Commit: 4dcb07f9960185a72471a1a806cdd23610314a3b
Parents: 36f16bb
Author: Josh Elser <el...@apache.org>
Authored: Tue Jan 3 17:46:45 2017 -0500
Committer: Josh Elser <el...@apache.org>
Committed: Wed Jan 4 19:36:24 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/4dcb07f9/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/4dcb07f9/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());
+ }
}
[4/5] hbase git commit: HBASE-17409 Limit jsonp callback name to
prevent xss
Posted by el...@apache.org.
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 <el...@apache.org>
Authored: Tue Jan 3 17:46:45 2017 -0500
Committer: Josh Elser <el...@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());
+ }
}
[3/5] hbase git commit: HBASE-17409 Limit jsonp callback name to
prevent xss
Posted by el...@apache.org.
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/1829cd54
Tree: http://git-wip-us.apache.org/repos/asf/hbase/tree/1829cd54
Diff: http://git-wip-us.apache.org/repos/asf/hbase/diff/1829cd54
Branch: refs/heads/branch-1.3
Commit: 1829cd541ac722ef2a6a115cb3e45c1379c6ffd0
Parents: e359c76
Author: Josh Elser <el...@apache.org>
Authored: Tue Jan 3 17:46:45 2017 -0500
Committer: Josh Elser <el...@apache.org>
Committed: Wed Jan 4 19:36:47 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/1829cd54/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/1829cd54/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());
+ }
}
[5/5] hbase git commit: HBASE-17409 Limit jsonp callback name to
prevent xss
Posted by el...@apache.org.
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/63d8186d
Tree: http://git-wip-us.apache.org/repos/asf/hbase/tree/63d8186d
Diff: http://git-wip-us.apache.org/repos/asf/hbase/diff/63d8186d
Branch: refs/heads/branch-1.1
Commit: 63d8186d45c83bd0d31d6ae3750046b49000f38c
Parents: e32f8ac
Author: Josh Elser <el...@apache.org>
Authored: Tue Jan 3 17:46:45 2017 -0500
Committer: Josh Elser <el...@apache.org>
Committed: Wed Jan 4 19:37:39 2017 -0500
----------------------------------------------------------------------
.../hadoop/hbase/http/jmx/JMXJsonServlet.java | 27 +++++++++++++++++---
.../hbase/http/jmx/TestJMXJsonServlet.java | 25 ++++++++++++++++++
2 files changed, 48 insertions(+), 4 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/hbase/blob/63d8186d/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 b6e97a8..5d11267 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
@@ -145,7 +145,7 @@ public class JMXJsonServlet extends HttpServlet {
* The servlet response we are creating
*/
@Override
- public void doGet(HttpServletRequest request, HttpServletResponse response) {
+ public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
try {
if (!HttpServer.isInstrumentationAccessAllowed(getServletContext(), request, response)) {
return;
@@ -154,10 +154,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 + "(");
@@ -207,10 +207,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/63d8186d/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());
+ }
}