mirror of
https://github.com/github/codeql.git
synced 2026-04-30 19:26:02 +02:00
Fine tune the query
This commit is contained in:
@@ -3,7 +3,7 @@ public class UnsafeAndroidAccess extends Activity {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.webview);
|
||||
|
||||
// BAD: Have both JavaScript and universal resource access enabled in webview while
|
||||
// BAD: Have both JavaScript and cross-origin resource access enabled in webview while
|
||||
// taking remote user inputs
|
||||
{
|
||||
WebView wv = (WebView) findViewById(R.id.my_webview);
|
||||
@@ -24,7 +24,7 @@ public class UnsafeAndroidAccess extends Activity {
|
||||
wv.loadUrl(thisUrl);
|
||||
}
|
||||
|
||||
// BAD: Have both JavaScript and universal resource access enabled in webview while
|
||||
// BAD: Have both JavaScript and cross-origin resource access enabled in webview while
|
||||
// taking remote user inputs
|
||||
{
|
||||
WebView wv = (WebView) findViewById(R.id.my_webview);
|
||||
@@ -45,7 +45,7 @@ public class UnsafeAndroidAccess extends Activity {
|
||||
wv.loadUrl(thisUrl);
|
||||
}
|
||||
|
||||
// GOOD: Have JavaScript and universal resource access disabled by default on modern Android (Jellybean+) while taking remote user inputs
|
||||
// GOOD: Have JavaScript and cross-origin resource access disabled by default on modern Android (Jellybean+) while taking remote user inputs
|
||||
{
|
||||
WebView wv = (WebView) findViewById(-1);
|
||||
WebSettings webSettings = wv.getSettings();
|
||||
|
||||
@@ -8,12 +8,12 @@
|
||||
<p>This query detects the following two scenarios:</p>
|
||||
<ol>
|
||||
<li>Vulnerability introduced by WebViews with JavaScript enabled and remote inputs allowed.</li>
|
||||
<li>High precision vulnerability when allowing universal resource access is also enabled. The setting was just deprecated in API level 30 (Android 11) thus most devices are still affected given that Android phones don't get timely version updates like iPhones.</li>
|
||||
<li>A more severe vulnerability when allowing cross-origin resource access is also enabled. The setting was deprecated in API level 30 (Android 11), but most devices are still affected, especially given that some Android phones are updated slowly or no longer updated at all.</li>
|
||||
</ol>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>Only allow trusted web content to be displayed in WebViews when JavaScript is enabled. Disallow universal resource access in WebSetting to reduce the attack surface .</p>
|
||||
<p>Only allow trusted web content to be displayed in WebViews when JavaScript is enabled. Disallow cross-origin resource access in WebSetting to reduce the attack surface .</p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
@@ -28,4 +28,4 @@
|
||||
<a href="https://github.com/OWASP/owasp-mstg/blob/master/Document/0x05h-Testing-Platform-Interaction.md">OWASP - Testing WebView Protocol Handlers (MSTG-PLATFORM-5 and MSTG-PLATFORM-6)</a>
|
||||
</li>
|
||||
</references>
|
||||
</qhelp>
|
||||
</qhelp>
|
||||
@@ -13,7 +13,7 @@ import semmle.code.java.frameworks.android.WebView
|
||||
import semmle.code.java.dataflow.FlowSources
|
||||
|
||||
/**
|
||||
* Methods allowing any-local-file and universal access in the WebSettings class
|
||||
* Methods allowing any-local-file and cross-origin access in the WebSettings class
|
||||
*/
|
||||
class CrossOriginAccessMethod extends Method {
|
||||
CrossOriginAccessMethod() {
|
||||
@@ -36,12 +36,11 @@ class AllowJavaScriptMethod extends Method {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `ma` is a method invocation against `va` and `va.setJavaScriptEnabled(true)` occurs elsewhere in the program
|
||||
* Holds if a call to `v.setJavaScriptEnabled(true)` exists
|
||||
*/
|
||||
predicate isJSEnabled(Variable v) {
|
||||
exists(VarAccess va, MethodAccess jsa |
|
||||
v.getAnAccess() = va and
|
||||
jsa.getQualifier() = v.getAnAccess() and
|
||||
exists(MethodAccess jsa |
|
||||
v.getAnAccess() = jsa.getQualifier() and
|
||||
jsa.getMethod() instanceof AllowJavaScriptMethod and
|
||||
jsa.getArgument(0).(BooleanLiteral).getBooleanValue() = true
|
||||
)
|
||||
@@ -53,10 +52,7 @@ predicate isJSEnabled(Variable v) {
|
||||
class FetchResourceMethodAccess extends MethodAccess {
|
||||
FetchResourceMethodAccess() {
|
||||
this.getMethod().getDeclaringType() instanceof TypeWebView and
|
||||
(
|
||||
this.getMethod().hasName("loadUrl") or
|
||||
this.getMethod().hasName("postUrl")
|
||||
)
|
||||
this.getMethod().hasName(["loadUrl", "postUrl"])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,19 +80,7 @@ class UntrustedResourceSource extends RemoteFlowSource {
|
||||
)
|
||||
}
|
||||
|
||||
override string getSourceType() {
|
||||
result = "user input vulnerable to XSS and sensitive resource disclosure attacks" and
|
||||
exists(MethodAccess ma |
|
||||
ma.getMethod() instanceof CrossOriginAccessMethod and //High precision match of unsafe resource fetching
|
||||
ma.getArgument(0).(BooleanLiteral).getBooleanValue() = true
|
||||
)
|
||||
or
|
||||
result = "user input potentially vulnerable to XSS and sensitive resource disclosure attacks" and
|
||||
not exists(MethodAccess ma |
|
||||
ma.getMethod() instanceof CrossOriginAccessMethod and //High precision match of unsafe resource fetching
|
||||
ma.getArgument(0).(BooleanLiteral).getBooleanValue() = true
|
||||
)
|
||||
}
|
||||
override string getSourceType() { result = "UntrustedIntentExtraSource" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -111,6 +95,23 @@ class UrlResourceSink extends DataFlow::ExprNode {
|
||||
UrlResourceSink() { fetchResource(_, this.getExpr()) }
|
||||
|
||||
FetchResourceMethodAccess getMethodAccess() { fetchResource(result, this.getExpr()) }
|
||||
|
||||
predicate crossOriginAccessEnabled() {
|
||||
exists(MethodAccess ma, MethodAccess getSettingsMa |
|
||||
ma.getMethod() instanceof CrossOriginAccessMethod and // Unsafe resource fetching of more severe vulnerabilities
|
||||
ma.getArgument(0).(BooleanLiteral).getBooleanValue() = true and
|
||||
ma.getQualifier().(VarAccess).getVariable().getAnAssignedValue() = getSettingsMa and
|
||||
getSettingsMa.getMethod() instanceof WebViewGetSettingsMethod and
|
||||
getSettingsMa.getQualifier().(VarAccess).getVariable().getAnAccess() =
|
||||
getMethodAccess().getQualifier()
|
||||
)
|
||||
}
|
||||
|
||||
string getSinkType() {
|
||||
if crossOriginAccessEnabled()
|
||||
then result = "user input vulnerable to cross-origin and sensitive resource disclosure attacks"
|
||||
else result = "user input vulnerable to XSS attacks"
|
||||
}
|
||||
}
|
||||
|
||||
class FetchUntrustedResourceConfiguration extends TaintTracking::Configuration {
|
||||
@@ -118,18 +119,20 @@ class FetchUntrustedResourceConfiguration extends TaintTracking::Configuration {
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { source instanceof UntrustedResourceSource }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) { sink instanceof UrlResourceSink }
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
sink instanceof UrlResourceSink and
|
||||
exists(VarAccess webviewVa, MethodAccess getSettingsMa, Variable v |
|
||||
sink.(UrlResourceSink).getMethodAccess().getQualifier() = webviewVa and
|
||||
getSettingsMa.getMethod() instanceof WebViewGetSettingsMethod and
|
||||
webviewVa.getVariable().getAnAccess() = getSettingsMa.getQualifier() and
|
||||
v.getAnAssignedValue() = getSettingsMa and
|
||||
isJSEnabled(v)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
from DataFlow::PathNode source, DataFlow::PathNode sink, FetchUntrustedResourceConfiguration conf
|
||||
where
|
||||
exists(VarAccess webviewVa, MethodAccess getSettingsMa, Variable v |
|
||||
conf.hasFlowPath(source, sink) and
|
||||
sink.getNode().(UrlResourceSink).getMethodAccess().getQualifier() = webviewVa and
|
||||
webviewVa.getVariable().getAnAccess() = getSettingsMa.getQualifier() and
|
||||
v.getAnAssignedValue() = getSettingsMa and
|
||||
isJSEnabled(v)
|
||||
)
|
||||
where conf.hasFlowPath(source, sink)
|
||||
select sink.getNode().(UrlResourceSink).getMethodAccess(), source, sink,
|
||||
"Unsafe resource fetching in Android webview due to $@.", source.getNode(),
|
||||
source.getNode().(UntrustedResourceSource).getSourceType()
|
||||
sink.getNode().(UrlResourceSink).getSinkType()
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
| UnsafeAndroidAccess.java:30:3:30:21 | loadUrl(...) | UnsafeAndroidAccess.java:30:14:30:20 | thisUrl | UnsafeAndroidAccess.java:30:14:30:20 | thisUrl | Unsafe resource fetching in Android webview due to $@. | UnsafeAndroidAccess.java:30:14:30:20 | thisUrl | user input vulnerable to XSS and sensitive resource disclosure attacks |
|
||||
| UnsafeAndroidAccess.java:53:3:53:21 | loadUrl(...) | UnsafeAndroidAccess.java:53:14:53:20 | thisUrl | UnsafeAndroidAccess.java:53:14:53:20 | thisUrl | Unsafe resource fetching in Android webview due to $@. | UnsafeAndroidAccess.java:53:14:53:20 | thisUrl | user input vulnerable to XSS and sensitive resource disclosure attacks |
|
||||
| UnsafeAndroidAccess.java:30:3:30:21 | loadUrl(...) | UnsafeAndroidAccess.java:30:14:30:20 | thisUrl | UnsafeAndroidAccess.java:30:14:30:20 | thisUrl | Unsafe resource fetching in Android webview due to $@. | UnsafeAndroidAccess.java:30:14:30:20 | thisUrl | user input vulnerable to cross-origin and sensitive resource disclosure attacks |
|
||||
| UnsafeAndroidAccess.java:53:3:53:21 | loadUrl(...) | UnsafeAndroidAccess.java:53:14:53:20 | thisUrl | UnsafeAndroidAccess.java:53:14:53:20 | thisUrl | Unsafe resource fetching in Android webview due to $@. | UnsafeAndroidAccess.java:53:14:53:20 | thisUrl | user input vulnerable to cross-origin and sensitive resource disclosure attacks |
|
||||
| UnsafeAndroidAccess.java:95:3:95:21 | loadUrl(...) | UnsafeAndroidAccess.java:95:14:95:20 | thisUrl | UnsafeAndroidAccess.java:95:14:95:20 | thisUrl | Unsafe resource fetching in Android webview due to $@. | UnsafeAndroidAccess.java:95:14:95:20 | thisUrl | user input vulnerable to XSS attacks |
|
||||
|
||||
@@ -7,7 +7,7 @@ import android.webkit.WebView;
|
||||
import android.webkit.WebViewClient;
|
||||
|
||||
public class UnsafeAndroidAccess extends Activity {
|
||||
//Test onCreate with both JavaScript and universal resource access enabled while taking remote user inputs from bundle extras
|
||||
//Test onCreate with both JavaScript and cross-origin resource access enabled while taking remote user inputs from bundle extras
|
||||
public void testOnCreate1(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(-1);
|
||||
@@ -30,7 +30,7 @@ public class UnsafeAndroidAccess extends Activity {
|
||||
wv.loadUrl(thisUrl);
|
||||
}
|
||||
|
||||
//Test onCreate with both JavaScript and universal resource access enabled while taking remote user inputs from string extra
|
||||
//Test onCreate with both JavaScript and cross-origin resource access enabled while taking remote user inputs from string extra
|
||||
public void testOnCreate2(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(-1);
|
||||
@@ -53,7 +53,7 @@ public class UnsafeAndroidAccess extends Activity {
|
||||
wv.loadUrl(thisUrl);
|
||||
}
|
||||
|
||||
//Test onCreate with both JavaScript and universal resource access disabled by default while taking remote user inputs
|
||||
//Test onCreate with both JavaScript and cross-origin resource access disabled by default while taking remote user inputs
|
||||
public void testOnCreate3(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(-1);
|
||||
@@ -73,7 +73,7 @@ public class UnsafeAndroidAccess extends Activity {
|
||||
wv.loadUrl(thisUrl);
|
||||
}
|
||||
|
||||
//Test onCreate with both JavaScript and universal resource access enabled while not taking remote user inputs
|
||||
//Test onCreate with JavaScript enabled but cross-origin resource access disabled while taking remote user inputs
|
||||
public void testOnCreate4(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(-1);
|
||||
@@ -81,6 +81,28 @@ public class UnsafeAndroidAccess extends Activity {
|
||||
WebView wv = (WebView) findViewById(-1);
|
||||
WebSettings webSettings = wv.getSettings();
|
||||
|
||||
webSettings.setJavaScriptEnabled(true);
|
||||
|
||||
wv.setWebViewClient(new WebViewClient() {
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView view, String url) {
|
||||
view.loadUrl(url);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
String thisUrl = getIntent().getStringExtra("url");
|
||||
wv.loadUrl(thisUrl);
|
||||
}
|
||||
|
||||
//Test onCreate with both JavaScript and cross-origin resource access enabled while not taking remote user inputs
|
||||
public void testOnCreate5(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(-1);
|
||||
|
||||
WebView wv = (WebView) findViewById(-1);
|
||||
WebSettings webSettings = wv.getSettings();
|
||||
|
||||
webSettings.setJavaScriptEnabled(true);
|
||||
webSettings.setAllowFileAccessFromFileURLs(true);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user