2
2
3
3
import java
4
4
import semmle.code.java.dataflow.FlowSources
5
+ import semmle.code.java.dataflow.DataFlow3
5
6
import semmle.code.java.dataflow.TaintTracking
6
7
import semmle.code.java.dataflow.TaintTracking2
7
8
import semmle.code.java.security.AndroidIntentRedirection
8
9
9
- /**
10
- * Holds if taint may flow from `source` to `sink` for `IntentRedirectionConfiguration`.
11
- *
12
- * It ensures that `ChangeIntentComponent` is an intermediate step in the flow.
13
- */
14
- predicate hasIntentRedirectionFlowPath ( DataFlow:: PathNode source , DataFlow:: PathNode sink ) {
15
- exists ( IntentRedirectionConfiguration conf , DataFlow:: PathNode intermediate |
16
- intermediate .getNode ( ) .( ChangeIntentComponent ) .hasFlowFrom ( source .getNode ( ) ) and
17
- conf .hasFlowPath ( intermediate , sink )
18
- )
19
- }
20
-
21
10
/**
22
11
* A taint tracking configuration for tainted Intents being used to start Android components.
23
12
*/
24
- private class IntentRedirectionConfiguration extends TaintTracking:: Configuration {
13
+ class IntentRedirectionConfiguration extends TaintTracking:: Configuration {
25
14
IntentRedirectionConfiguration ( ) { this = "IntentRedirectionConfiguration" }
26
15
27
- override predicate isSource ( DataFlow:: Node source ) {
28
- exists ( ChangeIntentComponent c |
29
- c = source
30
- or
31
- // This is needed for PathGraph to be able to build the full flow
32
- c .hasFlowFrom ( source )
33
- )
34
- }
16
+ override predicate isSource ( DataFlow:: Node source ) { source instanceof RemoteFlowSource }
35
17
36
18
override predicate isSink ( DataFlow:: Node sink ) { sink instanceof IntentRedirectionSink }
37
19
@@ -44,17 +26,48 @@ private class IntentRedirectionConfiguration extends TaintTracking::Configuratio
44
26
}
45
27
}
46
28
47
- /** An expression modifying an `Intent` component with tainted data. */
48
- private class ChangeIntentComponent extends DataFlow:: Node {
49
- DataFlow:: Node src ;
29
+ /**
30
+ * A sanitizer for sinks that receive the original incoming Intent,
31
+ * since its component cannot be arbitrarily set.
32
+ */
33
+ private class OriginalIntentSanitizer extends IntentRedirectionSanitizer {
34
+ OriginalIntentSanitizer ( ) { any ( SameIntentBeingRelaunchedConfiguration c ) .hasFlowTo ( this ) }
35
+ }
36
+
37
+ /**
38
+ * Data flow configuration used to discard incoming Intents
39
+ * flowing directly to sinks that start Android components.
40
+ */
41
+ private class SameIntentBeingRelaunchedConfiguration extends DataFlow3:: Configuration {
42
+ SameIntentBeingRelaunchedConfiguration ( ) { this = "SameIntentBeingRelaunchedConfiguration" }
43
+
44
+ override predicate isSource ( DataFlow:: Node source ) { source instanceof RemoteFlowSource }
50
45
51
- ChangeIntentComponent ( ) {
52
- changesIntentComponent ( this .asExpr ( ) ) and
53
- exists ( TaintedIntentComponentConf conf | conf .hasFlow ( src , this ) )
46
+ override predicate isSink ( DataFlow:: Node sink ) { sink instanceof IntentRedirectionSink }
47
+
48
+ override predicate isBarrier ( DataFlow:: Node barrier ) {
49
+ // Don't discard the Intent if its original component is tainted
50
+ barrier instanceof IntentWithTaintedComponent
51
+ }
52
+
53
+ override predicate isAdditionalFlowStep ( DataFlow:: Node node1 , DataFlow:: Node node2 ) {
54
+ // Intents being built with the copy constructor from the original Intent are discarded too
55
+ exists ( ClassInstanceExpr cie |
56
+ cie .getConstructedType ( ) instanceof TypeIntent and
57
+ node1 .asExpr ( ) = cie .getArgument ( 0 ) and
58
+ node2 .asExpr ( ) = cie
59
+ )
54
60
}
61
+ }
55
62
56
- /** Holds if `source` flows to `this`. */
57
- predicate hasFlowFrom ( DataFlow:: Node source ) { source = src }
63
+ /** An `Intent` with a tainted component. */
64
+ private class IntentWithTaintedComponent extends DataFlow:: Node {
65
+ IntentWithTaintedComponent ( ) {
66
+ exists ( IntentSetComponent setExpr , TaintedIntentComponentConf conf |
67
+ setExpr .getQualifier ( ) = this .asExpr ( ) and
68
+ conf .hasFlowTo ( DataFlow:: exprNode ( setExpr .getSink ( ) ) )
69
+ )
70
+ }
58
71
}
59
72
60
73
/**
@@ -65,25 +78,8 @@ private class TaintedIntentComponentConf extends TaintTracking2::Configuration {
65
78
66
79
override predicate isSource ( DataFlow:: Node source ) { source instanceof RemoteFlowSource }
67
80
68
- override predicate isSink ( DataFlow:: Node sink ) { changesIntentComponent ( sink .asExpr ( ) ) }
69
- }
70
-
71
- /** Holds if `expr` modifies the component of an `Intent`. */
72
- private predicate changesIntentComponent ( Expr expr ) {
73
- any ( IntentSetComponent isc ) .getSink ( ) = expr
74
- or
75
- // obtaining an arbitrary Intent as a Parcelable extra
76
- expr instanceof IntentGetParcelableExtra
77
- }
78
-
79
- /** A call to the method `Intent.getParcelableExtra`. */
80
- private class IntentGetParcelableExtra extends MethodAccess {
81
- IntentGetParcelableExtra ( ) {
82
- exists ( Method m |
83
- this .getMethod ( ) = m and
84
- m .getDeclaringType ( ) instanceof TypeIntent and
85
- m .hasName ( "getParcelableExtra" )
86
- )
81
+ override predicate isSink ( DataFlow:: Node sink ) {
82
+ any ( IntentSetComponent setComponent ) .getSink ( ) = sink .asExpr ( )
87
83
}
88
84
}
89
85
0 commit comments