10
10
*/
11
11
12
12
import java
13
- import semmle.code.java.dataflow.DataFlow
13
+ import semmle.code.java.dataflow.TaintTracking
14
14
import semmle.code.java.frameworks.android.WebView
15
15
16
+ /** Represents `android.webkit.WebView` and its subclasses. */
16
17
private class TypeWebViewOrSubclass extends RefType {
17
18
TypeWebViewOrSubclass ( ) { this .getASupertype * ( ) instanceof TypeWebView }
18
19
}
@@ -30,69 +31,70 @@ private class PrivateGetterMethodAccess extends MethodAccess {
30
31
}
31
32
}
32
33
33
- /**
34
- * A flow configuration for tracking flow from the creation of a `WebView` object to a call of the `getSettings` method.
35
- */
36
- private class WebViewGetSettingsConfiguration extends DataFlow:: Configuration {
37
- WebViewGetSettingsConfiguration ( ) { this = "WebViewGetSettingsConfiguration" }
38
-
39
- override predicate isSource ( DataFlow:: Node node ) {
40
- node .asExpr ( ) .getType ( ) .( RefType ) instanceof TypeWebViewOrSubclass and
34
+ /** A source for `android.webkit.WebView` objects. */
35
+ class WebViewSource extends DataFlow:: Node {
36
+ WebViewSource ( ) {
37
+ this .getType ( ) .( RefType ) instanceof TypeWebViewOrSubclass and
41
38
// To reduce duplicate results, we only consider WebView objects from
42
39
// constructor and method calls, or method accesses which are cast to WebView.
43
40
(
44
- node .asExpr ( ) instanceof ClassInstanceExpr or
45
- node .asExpr ( ) instanceof MethodAccess or
46
- node .asExpr ( ) .( CastExpr ) .getAChildExpr ( ) instanceof MethodAccess
41
+ this .asExpr ( ) instanceof ClassInstanceExpr or
42
+ this .asExpr ( ) instanceof MethodAccess or
43
+ this .asExpr ( ) .( CastExpr ) .getAChildExpr ( ) instanceof MethodAccess
47
44
) and
48
45
// Avoid duplicate results from Kotlin member accesses.
49
- not node .asExpr ( ) instanceof PrivateGetterMethodAccess
46
+ not this .asExpr ( ) instanceof PrivateGetterMethodAccess
50
47
}
48
+ }
51
49
52
- override predicate isSink ( DataFlow:: Node node ) {
50
+ /**
51
+ * A sink representing a call to `android.webkit.WebSettings.setAllowContentAccess` that
52
+ * disables content access.
53
+ */
54
+ class WebSettingsDisallowContentAccessSink extends DataFlow:: Node {
55
+ WebSettingsDisallowContentAccessSink ( ) {
53
56
exists ( MethodAccess ma |
54
- ma .getQualifier ( ) = node .asExpr ( ) and
55
- ma .getMethod ( ) instanceof WebViewGetSettingsMethod
57
+ ma .getQualifier ( ) = this .asExpr ( ) and
58
+ ma .getMethod ( ) instanceof AllowContentAccessMethod and
59
+ ma .getArgument ( 0 ) .( BooleanLiteral ) .getBooleanValue ( ) = false
56
60
)
57
61
}
58
62
}
59
63
60
- private class WebSettingsSetAllowContentAccessFalseConfiguration extends DataFlow:: Configuration {
61
- WebSettingsSetAllowContentAccessFalseConfiguration ( ) {
62
- this = "WebSettingsSetAllowContentAccessFalseConfiguration"
63
- }
64
+ class WebViewDisallowContentAccessConfiguration extends TaintTracking:: Configuration {
65
+ WebViewDisallowContentAccessConfiguration ( ) { this = "WebViewDisallowContentAccessConfiguration" }
64
66
65
- override predicate isSource ( DataFlow:: Node node ) {
66
- node .asExpr ( ) .getType ( ) instanceof TypeWebSettings
67
+ override predicate isSource ( DataFlow:: Node node , DataFlow:: FlowState state ) {
68
+ state instanceof DataFlow:: FlowStateEmpty and
69
+ node instanceof WebViewSource
67
70
}
68
71
69
- override predicate isSink ( DataFlow:: Node node ) {
70
- // sink: settings.setAllowContentAccess(false)
71
- // or (in Kotlin): settings.allowContentAccess = false
72
+ /**
73
+ * Holds if the step from `node1` to `node2` is a dataflow step that gets the `WebSettings` object
74
+ * from the `getSettings` method of a `WebView` object.
75
+ */
76
+ override predicate isAdditionalTaintStep (
77
+ DataFlow:: Node node1 , DataFlow:: FlowState state1 , DataFlow:: Node node2 ,
78
+ DataFlow:: FlowState state2
79
+ ) {
80
+ state1 instanceof DataFlow:: FlowStateEmpty and
81
+ state2 = "WebSettings" and
82
+ // settings = webView.getSettings()
83
+ // ^node2 = ^node1
72
84
exists ( MethodAccess ma |
73
- ma . getQualifier ( ) = node .asExpr ( ) and
74
- ma .getMethod ( ) . hasName ( "setAllowContentAccess" ) and
75
- ma .getArgument ( 0 ) . ( CompileTimeConstantExpr ) . getBooleanValue ( ) = false
85
+ ma = node2 .asExpr ( ) and
86
+ ma .getQualifier ( ) = node1 . asExpr ( ) and
87
+ ma .getMethod ( ) instanceof WebViewGetSettingsMethod
76
88
)
77
89
}
78
- }
79
90
80
- predicate hasContentAccessDisabled ( Expr webview ) {
81
- exists (
82
- DataFlow:: Node wvSource , DataFlow:: Node wvSink , WebViewGetSettingsConfiguration viewCfg ,
83
- DataFlow:: Node settingsSource , DataFlow:: Node settingsSink ,
84
- WebSettingsSetAllowContentAccessFalseConfiguration settingsCfg , MethodAccess getSettingsAccess
85
- |
86
- wvSource = DataFlow:: exprNode ( webview ) and
87
- viewCfg .hasFlow ( wvSource , wvSink ) and
88
- settingsCfg .hasFlow ( settingsSource , settingsSink ) and
89
- getSettingsAccess .getQualifier ( ) = wvSink .asExpr ( ) and
90
- getSettingsAccess .getMethod ( ) instanceof WebViewGetSettingsMethod and
91
- getSettingsAccess = settingsSource .asExpr ( )
92
- )
91
+ override predicate isSink ( DataFlow:: Node node , DataFlow:: FlowState state ) {
92
+ state = "WebSettings" and
93
+ node instanceof WebSettingsDisallowContentAccessSink
94
+ }
93
95
}
94
96
95
- from Expr source , WebViewGetSettingsConfiguration cfg
96
- where cfg . isSource ( DataFlow :: exprNode ( source ) ) and not hasContentAccessDisabled ( source )
97
+ from WebViewSource source
98
+ where not any ( WebViewDisallowContentAccessConfiguration cfg ) . hasFlow ( source , _ )
97
99
select source ,
98
100
"Sensitive information may be exposed via a malicious link due to access of content:// links being permitted."
0 commit comments