1010 */
1111
1212import java
13- import semmle.code.java.dataflow.DataFlow
13+ import semmle.code.java.dataflow.TaintTracking
1414import semmle.code.java.frameworks.android.WebView
1515
16+ /** Represents `android.webkit.WebView` and its subclasses. */
1617private class TypeWebViewOrSubclass extends RefType {
1718 TypeWebViewOrSubclass ( ) { this .getASupertype * ( ) instanceof TypeWebView }
1819}
@@ -30,69 +31,70 @@ private class PrivateGetterMethodAccess extends MethodAccess {
3031 }
3132}
3233
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
4138 // To reduce duplicate results, we only consider WebView objects from
4239 // constructor and method calls, or method accesses which are cast to WebView.
4340 (
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
4744 ) and
4845 // Avoid duplicate results from Kotlin member accesses.
49- not node .asExpr ( ) instanceof PrivateGetterMethodAccess
46+ not this .asExpr ( ) instanceof PrivateGetterMethodAccess
5047 }
48+ }
5149
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 ( ) {
5356 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
5660 )
5761 }
5862}
5963
60- private class WebSettingsSetAllowContentAccessFalseConfiguration extends DataFlow:: Configuration {
61- WebSettingsSetAllowContentAccessFalseConfiguration ( ) {
62- this = "WebSettingsSetAllowContentAccessFalseConfiguration"
63- }
64+ class WebViewDisallowContentAccessConfiguration extends TaintTracking:: Configuration {
65+ WebViewDisallowContentAccessConfiguration ( ) { this = "WebViewDisallowContentAccessConfiguration" }
6466
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
6770 }
6871
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
7284 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
7688 )
7789 }
78- }
7990
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+ }
9395}
9496
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 , _ )
9799select source ,
98100 "Sensitive information may be exposed via a malicious link due to access of content:// links being permitted."
0 commit comments