@@ -5,15 +5,9 @@ private import semmle.code.java.dataflow.SSA
55private import semmle.code.java.dataflow.DefUse
66private import semmle.code.java.security.SecurityTests
77private import semmle.code.java.security.Validation
8- private import semmle.code.java.frameworks.android.Intent
9- private import semmle.code.java.frameworks.android.SQLite
10- private import semmle.code.java.frameworks.Guice
11- private import semmle.code.java.frameworks.Protobuf
12- private import semmle.code.java.frameworks.spring.SpringController
13- private import semmle.code.java.frameworks.spring.SpringHttp
148private import semmle.code.java.Maps
159private import semmle.code.java.dataflow.internal.ContainerFlow
16- private import semmle.code.java.frameworks.jackson.JacksonSerializability
10+ private import semmle.code.java.dataflow.TaintTrackingFrameworks
1711
1812/**
1913 * 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) {
7872 any ( AdditionalTaintStep a ) .step ( src , sink )
7973}
8074
75+ /**
76+ * A method that returns tainted data when one of its inputs (an argument or the qualifier) are tainted.
77+ *
78+ * Extend this class to add additional taint steps through a method that should
79+ * apply to all taint configurations.
80+ */
81+ abstract class TaintPreservingMethod extends Method {
82+ /**
83+ * Holds if this method returns tainted data when `arg` tainted.
84+ * `arg` is a parameter index, or is -1 to indicate the qualifier.
85+ */
86+ abstract predicate returnsTaint ( int arg ) ;
87+ }
88+
89+ /**
90+ * A method that transfers taint from one of its inputs (an argument or the qualifier) to another.
91+ *
92+ * Extend this class to add additional taint steps through a method that should
93+ * apply to all taint configurations.
94+ */
95+ abstract class TaintTransferringMethod extends Method {
96+ /**
97+ * Holds if this method writes tainted data to `sink` when `src` is tainted.
98+ * `src` and `sink` are parameter indices, or -1 to indicate the qualifier.
99+ */
100+ predicate transfersTaint ( int src , int sink ) { none ( ) }
101+ }
102+
81103/**
82104 * Holds if `node` should be a sanitizer in all global taint flow configurations
83105 * but not in local taint.
@@ -300,6 +322,8 @@ private predicate taintPreservingQualifierToArgument(Method m, int arg) {
300322 m .getDeclaringType ( ) .getASupertype * ( ) .hasQualifiedName ( "java.io" , "Reader" ) and
301323 m .hasName ( "read" ) and
302324 arg = 0
325+ or
326+ m .( TaintTransferringMethod ) .transfersTaint ( - 1 , arg )
303327}
304328
305329/** Access to a method that passes taint from the qualifier. */
@@ -412,6 +436,8 @@ private predicate taintPreservingQualifierToMethod(Method m) {
412436 // buildUnionSubQuery(String typeDiscriminatorColumn, String[] unionColumns, Set<String> columnsPresentInTable, int computedColumnsOffset, String typeDiscriminatorValue, String selection, String[] selectionArgs, String groupBy, String having)
413437 // buildUnionSubQuery(String typeDiscriminatorColumn, String[] unionColumns, Set<String> columnsPresentInTable, int computedColumnsOffset, String typeDiscriminatorValue, String selection, String groupBy, String having)
414438 m .hasName ( [ "buildQuery" , "buildUnionQuery" , "buildUnionSubQuery" ] )
439+ or
440+ m .( TaintPreservingMethod ) .returnsTaint ( - 1 )
415441}
416442
417443private class StringReplaceMethod extends Method {
@@ -429,7 +455,7 @@ private predicate unsafeEscape(MethodAccess ma) {
429455 // Removing `<script>` tags using a string-replace method is
430456 // unsafe if such a tag is embedded inside another one (e.g. `<scr<script>ipt>`).
431457 exists ( StringReplaceMethod m | ma .getMethod ( ) = m |
432- ma .getArgument ( 0 ) .( StringLiteral ) .getRepresentedString ( ) = "( <script>) " and
458+ ma .getArgument ( 0 ) .( StringLiteral ) .getRepresentedString ( ) = "<script>" and
433459 ma .getArgument ( 1 ) .( StringLiteral ) .getRepresentedString ( ) = ""
434460 )
435461}
@@ -620,6 +646,8 @@ private predicate taintPreservingArgumentToMethod(Method method, int arg) {
620646 // Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)
621647 method .hasName ( "query" ) and
622648 arg = 0
649+ or
650+ method .( TaintPreservingMethod ) .returnsTaint ( arg )
623651}
624652
625653/**
@@ -678,6 +706,8 @@ private predicate taintPreservingArgToArg(Method method, int input, int output)
678706 method .hasName ( "appendColumns" ) and
679707 input = 1 and
680708 output = 0
709+ or
710+ method .( TaintTransferringMethod ) .transfersTaint ( input , output )
681711}
682712
683713/**
@@ -737,6 +767,8 @@ private predicate taintPreservingArgumentToQualifier(Method method, int arg) {
737767 // appendWhereStandalone(CharSequence inWhere)
738768 method .hasName ( [ "setProjectionMap" , "setTables" , "appendWhere" , "appendWhereStandalone" ] ) and
739769 arg = 0
770+ or
771+ method .( TaintTransferringMethod ) .transfersTaint ( arg , - 1 )
740772}
741773
742774/** A comparison or equality test with a constant. */
0 commit comments