Skip to content

Commit 62158c5

Browse files
authored
Merge pull request github#12044 from atorralba/atorralba/webview-models
Swift: Add new source and flow step related to WkWebView
2 parents 7271d99 + 24527bf commit 62158c5

File tree

6 files changed

+515
-388
lines changed

6 files changed

+515
-388
lines changed

swift/ql/lib/codeql/swift/frameworks/StandardLibrary/WebView.qll

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,58 @@ private class WKScriptMessageBodyInheritsTaint extends TaintInheritingContent,
3333
}
3434
}
3535

36+
/**
37+
* A type or extension delcaration that adopts the protocol `WKNavigationDelegate`.
38+
*/
39+
private class AdoptsWkNavigationDelegate extends Decl {
40+
AdoptsWkNavigationDelegate() {
41+
exists(ProtocolDecl delegate |
42+
this.(ExtensionDecl).getAProtocol().getABaseTypeDecl*() = delegate or
43+
this.(NominalTypeDecl).getABaseTypeDecl*() = delegate
44+
|
45+
delegate.getName() = "WKNavigationDelegate"
46+
)
47+
}
48+
}
49+
50+
/**
51+
* A source for the `decidePolicyFor` parameter of the `webView` method of a type adopting `WKNavigationDelegate`.
52+
*/
53+
private class WKNavigationDelegateSource extends RemoteFlowSource {
54+
WKNavigationDelegateSource() {
55+
exists(ParamDecl p, FuncDecl f, AdoptsWkNavigationDelegate t |
56+
t.getAMember() = f and
57+
f.getName() =
58+
[
59+
"webView(_:decidePolicyFor:preferences:decisionHandler:)",
60+
"webView(_:decidePolicyFor:decisionHandler:)"
61+
] and
62+
p.getDeclaringFunction() = f and
63+
p.getIndex() = 1 and
64+
this.(DataFlow::ParameterNode).getParameter() = p
65+
)
66+
}
67+
68+
override string getSourceType() { result = "Navigation action of a WebView" }
69+
}
70+
71+
/**
72+
* A taint step implying that, if a `WKNavigationAction` is tainted, its `request` field is also tainted.
73+
*/
74+
private class WKNavigationActionTaintStep extends AdditionalTaintStep {
75+
override predicate step(DataFlow::Node n1, DataFlow::Node n2) {
76+
exists(MemberRefExpr e, Expr self, VarDecl member |
77+
self.getType().getName() = "WKNavigationAction" and
78+
member.getName() = "request"
79+
|
80+
e.getBase() = self and
81+
e.getMember() = member and
82+
n1.asExpr() = self and
83+
n2.asExpr() = e
84+
)
85+
}
86+
}
87+
3688
/**
3789
* A model for `JSContext` sources. `JSContext` acts as a bridge between JavaScript and
3890
* native code, so any object obtained from it has the potential of being tainted by a malicious

swift/ql/test/library-tests/dataflow/flowsources/FlowSources.expected

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -94,10 +94,16 @@
9494
| url.swift:53:15:53:19 | .resourceBytes | external |
9595
| url.swift:60:15:60:19 | .lines | external |
9696
| url.swift:67:16:67:22 | .lines | external |
97-
| webview.swift:20:82:20:102 | message | external |
98-
| webview.swift:25:5:25:13 | .globalObject | external |
99-
| webview.swift:26:5:26:39 | call to objectForKeyedSubscript(_:) | external |
100-
| webview.swift:39:9:39:9 | .tainted | Member of a type exposed through JSExport |
101-
| webview.swift:43:10:43:10 | self | Member of a type exposed through JSExport |
102-
| webview.swift:43:18:43:24 | arg1 | Member of a type exposed through JSExport |
103-
| webview.swift:43:29:43:35 | arg2 | Member of a type exposed through JSExport |
97+
| webview.swift:13:32:13:49 | decidePolicyFor | Navigation action of a WebView |
98+
| webview.swift:14:32:14:49 | decidePolicyFor | Navigation action of a WebView |
99+
| webview.swift:41:82:41:102 | message | external |
100+
| webview.swift:46:5:46:13 | .globalObject | external |
101+
| webview.swift:47:5:47:39 | call to objectForKeyedSubscript(_:) | external |
102+
| webview.swift:60:9:60:9 | .tainted | Member of a type exposed through JSExport |
103+
| webview.swift:64:10:64:10 | self | Member of a type exposed through JSExport |
104+
| webview.swift:64:18:64:24 | arg1 | Member of a type exposed through JSExport |
105+
| webview.swift:64:29:64:35 | arg2 | Member of a type exposed through JSExport |
106+
| webview.swift:72:32:72:49 | decidePolicyFor | Navigation action of a WebView |
107+
| webview.swift:73:32:73:49 | decidePolicyFor | Navigation action of a WebView |
108+
| webview.swift:79:32:79:49 | decidePolicyFor | Navigation action of a WebView |
109+
| webview.swift:80:32:80:49 | decidePolicyFor | Navigation action of a WebView |

swift/ql/test/library-tests/dataflow/flowsources/webview.swift

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,39 @@
11

22
// --- stubs ---
3+
34
class WKUserContentController {}
5+
46
class WKScriptMessage {}
7+
58
protocol WKScriptMessageHandler {
69
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage)
710
}
11+
12+
protocol WKNavigationDelegate {
13+
func webView(_: WKWebView, decidePolicyFor: WKNavigationAction, preferences: WKWebpagePreferences, decisionHandler: (WKNavigationActionPolicy, WKWebpagePreferences) -> Void)
14+
func webView(_: WKWebView, decidePolicyFor: WKNavigationAction, decisionHandler: (WKNavigationActionPolicy) -> Void)
15+
}
16+
17+
class WKWebView {}
18+
19+
class WKNavigationAction {}
20+
21+
class WKWebpagePreferences {}
22+
23+
enum WKNavigationActionPolicy {}
24+
825
protocol NSCopying {}
26+
927
protocol NSObjectProtocol {}
28+
1029
class JSValue {}
30+
1131
class JSContext {
1232
var globalObject: JSValue { get { return JSValue() } }
1333
func objectForKeyedSubscript(_: Any!) -> JSValue! { return JSValue() }
1434
func setObject(_: Any, forKeyedSubscript: (NSCopying & NSObjectProtocol) ) {}
1535
}
36+
1637
protocol JSExport {}
1738

1839
// --- tests ---
@@ -46,3 +67,15 @@ class ExportedImpl : Exported {
4667
func notTainted(arg1: Any, arg2: Any) {
4768
}
4869
}
70+
71+
class WebViewDelegate : WKNavigationDelegate {
72+
func webView(_: WKWebView, decidePolicyFor: WKNavigationAction, preferences: WKWebpagePreferences, decisionHandler: (WKNavigationActionPolicy, WKWebpagePreferences) -> Void) {} // SOURCE
73+
func webView(_: WKWebView, decidePolicyFor: WKNavigationAction, decisionHandler: (WKNavigationActionPolicy) -> Void) {} // SOURCE
74+
}
75+
76+
class Extended {}
77+
78+
extension Extended : WKNavigationDelegate {
79+
func webView(_: WKWebView, decidePolicyFor: WKNavigationAction, preferences: WKWebpagePreferences, decisionHandler: (WKNavigationActionPolicy, WKWebpagePreferences) -> Void) {} // SOURCE
80+
func webView(_: WKWebView, decidePolicyFor: WKNavigationAction, decisionHandler: (WKNavigationActionPolicy) -> Void) {} // SOURCE
81+
}

0 commit comments

Comments
 (0)