Skip to content

Commit 5265cb4

Browse files
committed
Merge two dataflow configurations into one taint tracking
1 parent 973f649 commit 5265cb4

File tree

1 file changed

+46
-44
lines changed

1 file changed

+46
-44
lines changed

java/ql/src/Security/CWE/CWE-200/AndroidWebViewSettingsPermitsContentAccess.ql

Lines changed: 46 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@
1010
*/
1111

1212
import java
13-
import semmle.code.java.dataflow.DataFlow
13+
import semmle.code.java.dataflow.TaintTracking
1414
import semmle.code.java.frameworks.android.WebView
1515

16+
/** Represents `android.webkit.WebView` and its subclasses. */
1617
private 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, _)
9799
select source,
98100
"Sensitive information may be exposed via a malicious link due to access of content:// links being permitted."

0 commit comments

Comments
 (0)