You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@spark.apache.org by hv...@apache.org on 2017/01/24 22:35:29 UTC

spark git commit: [SPARK-19334][SQL] Fix the code injection vulnerability related to Generator functions.

Repository: spark
Updated Branches:
  refs/heads/master cdb691eb4 -> 15ef3740d


[SPARK-19334][SQL] Fix the code injection vulnerability related to Generator functions.

## What changes were proposed in this pull request?

Similar to SPARK-15165, codegen is in danger of arbitrary code injection. The root cause is how variable names are created by codegen.
In GenerateExec#codeGenAccessor, a variable name is created like as follows.

```
val value = ctx.freshName(name)
```

The variable `value` is named based on the value of the variable `name` and the value of `name` is from schema given by users so an attacker can attack with queries like as follows.

```
SELECT inline(array(cast(struct(1) AS struct<`=new Object() { {f();} public void f() {throw new RuntimeException("This exception is injected.");} public int x;}.x`:int>)))
```

In the example above, a RuntimeException is thrown but an attacker can replace it with arbitrary code.

## How was this patch tested?

Added a new test case.

Author: Kousuke Saruta <sa...@oss.nttdata.co.jp>

Closes #16681 from sarutak/SPARK-19334.


Project: http://git-wip-us.apache.org/repos/asf/spark/repo
Commit: http://git-wip-us.apache.org/repos/asf/spark/commit/15ef3740
Tree: http://git-wip-us.apache.org/repos/asf/spark/tree/15ef3740
Diff: http://git-wip-us.apache.org/repos/asf/spark/diff/15ef3740

Branch: refs/heads/master
Commit: 15ef3740dea3d82f64a030d4523ad542485e1453
Parents: cdb691e
Author: Kousuke Saruta <sa...@oss.nttdata.co.jp>
Authored: Tue Jan 24 23:35:23 2017 +0100
Committer: Herman van Hovell <hv...@databricks.com>
Committed: Tue Jan 24 23:35:23 2017 +0100

----------------------------------------------------------------------
 .../apache/spark/sql/execution/GenerateExec.scala   | 11 +++++++++--
 .../scala/org/apache/spark/sql/SQLQuerySuite.scala  | 16 ++++++++++++++++
 2 files changed, 25 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/spark/blob/15ef3740/sql/core/src/main/scala/org/apache/spark/sql/execution/GenerateExec.scala
----------------------------------------------------------------------
diff --git a/sql/core/src/main/scala/org/apache/spark/sql/execution/GenerateExec.scala b/sql/core/src/main/scala/org/apache/spark/sql/execution/GenerateExec.scala
index b52f5c4..69be709 100644
--- a/sql/core/src/main/scala/org/apache/spark/sql/execution/GenerateExec.scala
+++ b/sql/core/src/main/scala/org/apache/spark/sql/execution/GenerateExec.scala
@@ -181,7 +181,14 @@ case class GenerateExec(
         val row = codeGenAccessor(ctx, data.value, "col", index, st, nullable, checks)
         val fieldChecks = checks ++ optionalCode(nullable, row.isNull)
         val columns = st.fields.toSeq.zipWithIndex.map { case (f, i) =>
-          codeGenAccessor(ctx, row.value, f.name, i.toString, f.dataType, f.nullable, fieldChecks)
+          codeGenAccessor(
+            ctx,
+            row.value,
+            s"st_col${i}",
+            i.toString,
+            f.dataType,
+            f.nullable,
+            fieldChecks)
         }
         ("", row.code, columns)
 
@@ -247,7 +254,7 @@ case class GenerateExec(
     val values = e.dataType match {
       case ArrayType(st: StructType, nullable) =>
         st.fields.toSeq.zipWithIndex.map { case (f, i) =>
-          codeGenAccessor(ctx, current, f.name, s"$i", f.dataType, f.nullable, checks)
+          codeGenAccessor(ctx, current, s"st_col${i}", s"$i", f.dataType, f.nullable, checks)
         }
     }
 

http://git-wip-us.apache.org/repos/asf/spark/blob/15ef3740/sql/core/src/test/scala/org/apache/spark/sql/SQLQuerySuite.scala
----------------------------------------------------------------------
diff --git a/sql/core/src/test/scala/org/apache/spark/sql/SQLQuerySuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/SQLQuerySuite.scala
index 07b787a..a77f920 100644
--- a/sql/core/src/test/scala/org/apache/spark/sql/SQLQuerySuite.scala
+++ b/sql/core/src/test/scala/org/apache/spark/sql/SQLQuerySuite.scala
@@ -2548,4 +2548,20 @@ class SQLQuerySuite extends QueryTest with SharedSQLContext {
       checkAnswer( sql("SELECT * FROM `_tbl`"), Row(1) :: Row(2) :: Row(3) :: Nil)
     }
   }
+
+  test("SPARK-19334: check code injection is prevented") {
+    // The end of comment (*/) should be escaped.
+    val badQuery =
+      """|SELECT inline(array(cast(struct(1) AS
+         |  struct<`=
+         |    new Object() {
+         |      {f();}
+         |      public void f() {throw new RuntimeException("This exception is injected.");}
+         |      public int x;
+         |    }.x
+         |  `:int>)))""".stripMargin.replaceAll("\n", "")
+
+    checkAnswer(sql(badQuery), Row(1) :: Nil)
+  }
+
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@spark.apache.org
For additional commands, e-mail: commits-help@spark.apache.org