From 551d86c6eae8c2ff5e89509a4e449ab058970d98 Mon Sep 17 00:00:00 2001 From: Joe Farebrother Date: Mon, 5 Oct 2020 11:33:12 +0100 Subject: [PATCH 01/16] Java: Define classes for taint propagation methods --- .../java/dataflow/TaintTrackingFrameworks.qll | 12 +++++ .../dataflow/internal/TaintTrackingUtil.qll | 48 +++++++++++++++---- 2 files changed, 52 insertions(+), 8 deletions(-) create mode 100644 java/ql/src/semmle/code/java/dataflow/TaintTrackingFrameworks.qll diff --git a/java/ql/src/semmle/code/java/dataflow/TaintTrackingFrameworks.qll b/java/ql/src/semmle/code/java/dataflow/TaintTrackingFrameworks.qll new file mode 100644 index 000000000000..26463c33d1ee --- /dev/null +++ b/java/ql/src/semmle/code/java/dataflow/TaintTrackingFrameworks.qll @@ -0,0 +1,12 @@ +/** + * Provides taint tracking information for frameworks. + * When a new framework is added that provides taint tracking steps, it should be imported here. + */ + +import semmle.code.java.frameworks.jackson.JacksonSerializability +import semmle.code.java.frameworks.android.Intent +import semmle.code.java.frameworks.android.SQLite +import semmle.code.java.frameworks.Guice +import semmle.code.java.frameworks.Protobuf +import semmle.code.java.frameworks.spring.SpringController +import semmle.code.java.frameworks.spring.SpringHttp diff --git a/java/ql/src/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll b/java/ql/src/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll index 8818dc37b1a6..833e849680f2 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll @@ -5,15 +5,9 @@ private import semmle.code.java.dataflow.SSA private import semmle.code.java.dataflow.DefUse private import semmle.code.java.security.SecurityTests private import semmle.code.java.security.Validation -private import semmle.code.java.frameworks.android.Intent -private import semmle.code.java.frameworks.android.SQLite -private import semmle.code.java.frameworks.Guice -private import semmle.code.java.frameworks.Protobuf -private import semmle.code.java.frameworks.spring.SpringController -private import semmle.code.java.frameworks.spring.SpringHttp private import semmle.code.java.Maps private import semmle.code.java.dataflow.internal.ContainerFlow -private import semmle.code.java.frameworks.jackson.JacksonSerializability +private import semmle.code.java.dataflow.TaintTrackingFrameworks /** * Holds if taint can flow from `src` to `sink` in zero or more @@ -78,6 +72,34 @@ predicate defaultAdditionalTaintStep(DataFlow::Node src, DataFlow::Node sink) { any(AdditionalTaintStep a).step(src, sink) } +/** + * A method that returns tainted data when one of its inputs (an argument or the qualifier) are tainted. + * + * Extend this class to add additional taint steps through a method that should + * apply to all taint configurations. + */ +abstract class TaintPreservingMethod extends Method { + /** + * Holds if this method returns tainted data when `arg` tainted. + * `arg` is a parameter index, or is -1 to indicate the qualifier. + */ + abstract predicate returnsTaint(int arg); +} + +/** + * A method that transfers taint from one of its inputs (an argument or the qualifier) to another. + * + * Extend this class to add additional taint steps through a method that should + * apply to all taint configurations. + */ +abstract class TaintTransferringMethod extends Method { + /** + * Holds if this method writes tainted data to `sink` when `src` is tainted. + * `src` and `sink` are parameter indices, or -1 to indicate the qualifier. + */ + predicate transfersTaint(int src, int sink) { none() } +} + /** * Holds if `node` should be a sanitizer in all global taint flow configurations * but not in local taint. @@ -300,6 +322,8 @@ private predicate taintPreservingQualifierToArgument(Method m, int arg) { m.getDeclaringType().getASupertype*().hasQualifiedName("java.io", "Reader") and m.hasName("read") and arg = 0 + or + m.(TaintTransferringMethod).transfersTaint(-1, arg) } /** Access to a method that passes taint from the qualifier. */ @@ -412,6 +436,8 @@ private predicate taintPreservingQualifierToMethod(Method m) { // buildUnionSubQuery(String typeDiscriminatorColumn, String[] unionColumns, Set columnsPresentInTable, int computedColumnsOffset, String typeDiscriminatorValue, String selection, String[] selectionArgs, String groupBy, String having) // buildUnionSubQuery(String typeDiscriminatorColumn, String[] unionColumns, Set columnsPresentInTable, int computedColumnsOffset, String typeDiscriminatorValue, String selection, String groupBy, String having) m.hasName(["buildQuery", "buildUnionQuery", "buildUnionSubQuery"]) + or + m.(TaintPreservingMethod).returnsTaint(-1) } private class StringReplaceMethod extends Method { @@ -429,7 +455,7 @@ private predicate unsafeEscape(MethodAccess ma) { // Removing `