33 */
44
55import java
6- private import semmle.code.java.frameworks.android.WebView
76private import semmle.code.java.dataflow.DataFlow
8- private import semmle.code.java.dataflow.ExternalFlow
7+ private import semmle.code.java.frameworks.android.WebView
98
109/**
1110 * A sink that represents a method that fetches a web resource in Android.
@@ -26,11 +25,9 @@ abstract class UrlResourceSink extends DataFlow::Node {
2625 */
2726private class CrossOriginUrlResourceSink extends JavaScriptEnabledUrlResourceSink {
2827 CrossOriginUrlResourceSink ( ) {
29- exists ( Variable settings , MethodAccess ma |
30- webViewLoadUrl ( this .asExpr ( ) , settings ) and
31- ma .getMethod ( ) instanceof CrossOriginAccessMethod and
32- ma .getArgument ( 0 ) .( BooleanLiteral ) .getBooleanValue ( ) = true and
33- ma .getQualifier ( ) = settings .getAnAccess ( )
28+ exists ( WebViewRef webview |
29+ webViewLoadUrl ( this .asExpr ( ) , webview ) and
30+ isAllowFileAccessEnabled ( webview )
3431 )
3532 }
3633
@@ -44,57 +41,96 @@ private class CrossOriginUrlResourceSink extends JavaScriptEnabledUrlResourceSin
4441 */
4542private class JavaScriptEnabledUrlResourceSink extends UrlResourceSink {
4643 JavaScriptEnabledUrlResourceSink ( ) {
47- exists ( Variable settings |
48- webViewLoadUrl ( this .asExpr ( ) , settings ) and
49- isJSEnabled ( settings )
44+ exists ( WebViewRef webview |
45+ webViewLoadUrl ( this .asExpr ( ) , webview ) and
46+ isJSEnabled ( webview )
5047 )
5148 }
5249
5350 override string getSinkType ( ) { result = "user input vulnerable to XSS attacks" }
5451}
5552
53+ private class WebViewRef extends Element {
54+ WebViewRef ( ) {
55+ this .( RefType ) .getASourceSupertype * ( ) instanceof TypeWebView or
56+ this .( Variable ) .getType ( ) .( RefType ) .getASourceSupertype * ( ) instanceof TypeWebView
57+ }
58+
59+ /** Gets an access to this WebView as a data flow node. */
60+ DataFlow:: Node getAnAccess ( ) {
61+ exists ( DataFlow:: InstanceAccessNode t | t .getType ( ) = this and result = t |
62+ t .isOwnInstanceAccess ( ) or t .getInstanceAccess ( ) .isEnclosingInstanceAccess ( this )
63+ )
64+ or
65+ result = DataFlow:: exprNode ( this .( Variable ) .getAnAccess ( ) )
66+ }
67+ }
68+
5669/**
57- * Holds if a `WebViewLoadUrlMethod` method is called with the given `urlArg` on a
58- * WebView with settings stored in `settings` .
70+ * Holds if a `WebViewLoadUrlMethod` is called on an access of `webview`
71+ * with `urlArg` as its first argument .
5972 */
60- private predicate webViewLoadUrl ( Expr urlArg , Variable settings ) {
61- exists ( MethodAccess loadUrl , Variable webview , MethodAccess getSettings |
73+ private predicate webViewLoadUrl ( Argument urlArg , WebViewRef webview ) {
74+ exists ( MethodAccess loadUrl |
6275 loadUrl .getArgument ( 0 ) = urlArg and
63- loadUrl .getMethod ( ) instanceof WebViewLoadUrlMethod and
64- loadUrl .getQualifier ( ) = webview .getAnAccess ( ) and
65- getSettings .getMethod ( ) instanceof WebViewGetSettingsMethod and
66- webview .getAnAccess ( ) = getSettings .getQualifier ( ) and
67- settings .getAnAssignedValue ( ) = getSettings
76+ loadUrl .getMethod ( ) instanceof WebViewLoadUrlMethod
77+ |
78+ webview .getAnAccess ( ) = DataFlow:: getInstanceArgument ( loadUrl )
79+ or
80+ // `webview` is received as a parameter of an event method in a custom `WebViewClient`,
81+ // so we need to find `WebViews` that use that specific `WebViewClient`.
82+ exists ( WebViewClientEventMethod eventMethod , MethodAccess setWebClient |
83+ setWebClient .getMethod ( ) instanceof WebViewSetWebViewClientMethod and
84+ setWebClient .getArgument ( 0 ) .getType ( ) = eventMethod .getDeclaringType ( ) and
85+ loadUrl .getQualifier ( ) = eventMethod .getWebViewParameter ( ) .getAnAccess ( )
86+ |
87+ webview .getAnAccess ( ) = DataFlow:: getInstanceArgument ( setWebClient )
88+ )
6889 )
6990}
7091
7192/**
72- * A method allowing any-local-file and cross-origin access in the WebSettings class.
93+ * Holds if `webview`'s option `setJavascriptEnabled`
94+ * has been set to `true` via a `WebSettings` object obtained from it.
7395 */
74- private class CrossOriginAccessMethod extends Method {
75- CrossOriginAccessMethod ( ) {
76- this .getDeclaringType ( ) instanceof TypeWebSettings and
77- this .hasName ( [ "setAllowUniversalAccessFromFileURLs" , "setAllowFileAccessFromFileURLs" ] )
78- }
96+ private predicate isJSEnabled ( WebViewRef webview ) {
97+ exists ( MethodAccess allowJs , MethodAccess settings |
98+ allowJs .getMethod ( ) instanceof AllowJavaScriptMethod and
99+ allowJs .getArgument ( 0 ) .( CompileTimeConstantExpr ) .getBooleanValue ( ) = true and
100+ settings .getMethod ( ) instanceof WebViewGetSettingsMethod and
101+ DataFlow:: localExprFlow ( settings , allowJs .getQualifier ( ) ) and
102+ DataFlow:: localFlow ( webview .getAnAccess ( ) , DataFlow:: getInstanceArgument ( settings ) )
103+ )
79104}
80105
81106/**
82- * The `setJavaScriptEnabled` method for the webview.
107+ * Holds if `webview`'s options `setAllowUniversalAccessFromFileURLs` or
108+ * `setAllowFileAccessFromFileURLs` have been set to `true` via a `WebSettings` object
109+ * obtained from it.
83110 */
84- private class AllowJavaScriptMethod extends Method {
85- AllowJavaScriptMethod ( ) {
86- this .getDeclaringType ( ) instanceof TypeWebSettings and
87- this .hasName ( "setJavaScriptEnabled" )
88- }
111+ private predicate isAllowFileAccessEnabled ( WebViewRef webview ) {
112+ exists ( MethodAccess allowFileAccess , MethodAccess settings |
113+ allowFileAccess .getMethod ( ) instanceof CrossOriginAccessMethod and
114+ allowFileAccess .getArgument ( 0 ) .( CompileTimeConstantExpr ) .getBooleanValue ( ) = true and
115+ settings .getMethod ( ) instanceof WebViewGetSettingsMethod and
116+ DataFlow:: localExprFlow ( settings , allowFileAccess .getQualifier ( ) ) and
117+ DataFlow:: localFlow ( webview .getAnAccess ( ) , DataFlow:: getInstanceArgument ( settings ) )
118+ )
89119}
90120
91- /**
92- * Holds if a call to `v.setJavaScriptEnabled(true)` exists.
93- */
94- private predicate isJSEnabled ( Variable v ) {
95- exists ( MethodAccess jsa |
96- v .getAnAccess ( ) = jsa .getQualifier ( ) and
97- jsa .getMethod ( ) instanceof AllowJavaScriptMethod and
98- jsa .getArgument ( 0 ) .( BooleanLiteral ) .getBooleanValue ( ) = true
99- )
121+ /** A method of the class `WebViewClient` that handles an event. */
122+ private class WebViewClientEventMethod extends Method {
123+ WebViewClientEventMethod ( ) {
124+ this .getDeclaringType ( ) .getASupertype * ( ) instanceof TypeWebViewClient and
125+ this .hasName ( [
126+ "shouldOverrideUrlLoading" , "shouldInterceptRequest" , "onPageStarted" , "onPageFinished" ,
127+ "onLoadResource" , "onPageCommitVisible" , "onTooManyRedirects"
128+ ] )
129+ }
130+
131+ /** Gets a `WebView` parameter of this method. */
132+ Parameter getWebViewParameter ( ) {
133+ result = this .getAParameter ( ) and
134+ result .getType ( ) instanceof TypeWebView
135+ }
100136}
0 commit comments