Fine tune the query

This commit is contained in:
luchua-bc
2020-10-14 16:16:15 +00:00
committed by Chris Smowton
parent 5338332648
commit c7750fd8c2
5 changed files with 70 additions and 44 deletions

View File

@@ -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();

View File

@@ -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>

View File

@@ -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()

View File

@@ -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 |

View File

@@ -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);