Skip to content

Commit 973f649

Browse files
committed
Break dataflow into two steps in order to capture flow from WebView to settings call
1 parent 0e15dd9 commit 973f649

File tree

1 file changed

+67
-14
lines changed

1 file changed

+67
-14
lines changed

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

Lines changed: 67 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,29 +17,82 @@ private class TypeWebViewOrSubclass extends RefType {
1717
TypeWebViewOrSubclass() { this.getASupertype*() instanceof TypeWebView }
1818
}
1919

20-
// source: WebView
21-
// sink: settings.setAllowContentAccess(false)
22-
class WebViewDisallowContentAccessConfiguration extends DataFlow::Configuration {
23-
WebViewDisallowContentAccessConfiguration() { this = "WebViewDisallowContentAccessConfiguration" }
20+
/**
21+
* A method access to a getter method which is private.
22+
*
23+
* In Kotlin, member accesses are translated to getter methods.
24+
*/
25+
private class PrivateGetterMethodAccess extends MethodAccess {
26+
PrivateGetterMethodAccess() {
27+
this instanceof MethodAccess and
28+
this.getMethod() instanceof GetterMethod and
29+
this.getMethod().isPrivate()
30+
}
31+
}
2432

25-
override predicate isSource(DataFlow::Node source) {
26-
source.asExpr().getType() instanceof TypeWebViewOrSubclass and
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
41+
// To reduce duplicate results, we only consider WebView objects from
42+
// constructor and method calls, or method accesses which are cast to WebView.
2743
(
28-
source.asExpr() instanceof ClassInstanceExpr or
29-
source.asExpr() instanceof MethodAccess or
30-
source.asExpr().(CastExpr).getAChildExpr() instanceof MethodAccess
44+
node.asExpr() instanceof ClassInstanceExpr or
45+
node.asExpr() instanceof MethodAccess or
46+
node.asExpr().(CastExpr).getAChildExpr() instanceof MethodAccess
47+
) and
48+
// Avoid duplicate results from Kotlin member accesses.
49+
not node.asExpr() instanceof PrivateGetterMethodAccess
50+
}
51+
52+
override predicate isSink(DataFlow::Node node) {
53+
exists(MethodAccess ma |
54+
ma.getQualifier() = node.asExpr() and
55+
ma.getMethod() instanceof WebViewGetSettingsMethod
3156
)
3257
}
58+
}
59+
60+
private class WebSettingsSetAllowContentAccessFalseConfiguration extends DataFlow::Configuration {
61+
WebSettingsSetAllowContentAccessFalseConfiguration() {
62+
this = "WebSettingsSetAllowContentAccessFalseConfiguration"
63+
}
3364

34-
override predicate isSink(DataFlow::Node sink) {
65+
override predicate isSource(DataFlow::Node node) {
66+
node.asExpr().getType() instanceof TypeWebSettings
67+
}
68+
69+
override predicate isSink(DataFlow::Node node) {
70+
// sink: settings.setAllowContentAccess(false)
71+
// or (in Kotlin): settings.allowContentAccess = false
3572
exists(MethodAccess ma |
36-
ma = sink.asExpr() and
73+
ma.getQualifier() = node.asExpr() and
3774
ma.getMethod().hasName("setAllowContentAccess") and
3875
ma.getArgument(0).(CompileTimeConstantExpr).getBooleanValue() = false
3976
)
4077
}
4178
}
4279

43-
from DataFlow::Node e, WebViewDisallowContentAccessConfiguration cfg
44-
where cfg.isSource(e) and not cfg.hasFlow(e, _)
45-
select e
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+
)
93+
}
94+
95+
from Expr source, WebViewGetSettingsConfiguration cfg
96+
where cfg.isSource(DataFlow::exprNode(source)) and not hasContentAccessDisabled(source)
97+
select source,
98+
"Sensitive information may be exposed via a malicious link due to access of content:// links being permitted."

0 commit comments

Comments
 (0)