Compare commits
8 Commits
rule/add-R
...
master
Author | SHA1 | Date | |
---|---|---|---|
![]() |
efc8e97d40 | ||
![]() |
ae0dfb3126 | ||
![]() |
cc01781c31 | ||
![]() |
5acd6984d0 | ||
![]() |
4e3c0d465a | ||
![]() |
266cde4510 | ||
![]() |
538d0b0b4f | ||
![]() |
6b9c19eceb |
@ -44,6 +44,7 @@
|
||||
* Java JWT
|
||||
* Java SE
|
||||
* Java JDBC API
|
||||
* Java I/O API
|
||||
* Jdom2
|
||||
* JSP
|
||||
* Legacy Mongo Java API
|
||||
|
@ -5191,6 +5191,7 @@
|
||||
"S1940": "sonar-kotlin 2.0.0.29",
|
||||
"S2053": "sonar-kotlin 2.3.0.609",
|
||||
"S2068": "sonar-kotlin 2.0.0.29",
|
||||
"S2083": "sonar-security master",
|
||||
"S2097": "sonar-kotlin 2.12.0.1956",
|
||||
"S2114": "sonar-kotlin 2.12.0.1956",
|
||||
"S2116": "sonar-kotlin 2.12.0.1956",
|
||||
@ -5222,6 +5223,7 @@
|
||||
"S5322": "sonar-kotlin 2.3.0.609",
|
||||
"S5324": "sonar-kotlin 2.2.0.499",
|
||||
"S5332": "sonar-kotlin 2.0.0.29",
|
||||
"S5344": "sonar-kotlin master",
|
||||
"S5527": "sonar-kotlin 2.0.0.29",
|
||||
"S5542": "sonar-kotlin 2.0.0.29",
|
||||
"S5547": "sonar-kotlin 2.0.0.29",
|
||||
@ -5235,6 +5237,7 @@
|
||||
"S5867": "sonar-kotlin 2.6.0.862",
|
||||
"S5868": "sonar-kotlin 2.6.0.862",
|
||||
"S5869": "sonar-kotlin 2.6.0.862",
|
||||
"S6096": "sonar-security master",
|
||||
"S6202": "sonar-kotlin 2.4.0.703",
|
||||
"S6207": "sonar-kotlin 2.15.0.2579",
|
||||
"S6218": "sonar-kotlin 2.4.0.703",
|
||||
@ -5257,6 +5260,7 @@
|
||||
"S6318": "sonar-kotlin 2.1.0.344",
|
||||
"S6362": "sonar-kotlin 2.5.0.754",
|
||||
"S6363": "sonar-kotlin 2.5.0.754",
|
||||
"S6384": "sonar-security master",
|
||||
"S6432": "sonar-kotlin 2.11.0.1828",
|
||||
"S6474": "sonar-kotlin master",
|
||||
"S6508": "sonar-kotlin 2.14.0.2352",
|
||||
@ -5292,6 +5296,7 @@
|
||||
"S7409": "sonar-kotlin master",
|
||||
"S7410": "sonar-kotlin master",
|
||||
"S7416": "sonar-kotlin master",
|
||||
"S7435": "sonar-kotlin master",
|
||||
"S899": "sonar-kotlin 2.12.0.1956"
|
||||
},
|
||||
"KUBERNETES": {
|
||||
|
@ -4,6 +4,10 @@ include::../ask-yourself.adoc[]
|
||||
|
||||
include::../recommended.adoc[]
|
||||
|
||||
=== Exceptions
|
||||
|
||||
* The rule ignores string literals that are used directly in Regexp methods.
|
||||
|
||||
== Sensitive Code Example
|
||||
|
||||
----
|
||||
|
@ -1,4 +1,4 @@
|
||||
== How to fix it in Java SE
|
||||
== How to fix it in Java I/O API
|
||||
|
||||
=== Code examples
|
||||
|
||||
@ -67,7 +67,7 @@ that the string `targetDirectory` does not end with a path separator:
|
||||
static private String targetDirectory = "/Users/John";
|
||||
|
||||
@GetMapping(value = "/endpoint")
|
||||
public void endpoint(@RequestParam("folder") fileName) throws IOException {
|
||||
public void endpoint(@RequestParam("folder") File fileName) throws IOException {
|
||||
|
||||
String canonicalizedFileName = fileName.getCanonicalPath();
|
||||
|
@ -6,7 +6,7 @@ include::../impact.adoc[]
|
||||
|
||||
// How to fix it section
|
||||
|
||||
include::how-to-fix-it/java-se.adoc[]
|
||||
include::how-to-fix-it/java-io-api.adoc[]
|
||||
|
||||
== Resources
|
||||
|
||||
|
94
rules/S2083/kotlin/how-to-fix-it/java-io-api.adoc
Normal file
94
rules/S2083/kotlin/how-to-fix-it/java-io-api.adoc
Normal file
@ -0,0 +1,94 @@
|
||||
== How to fix it in Java I/O API
|
||||
|
||||
=== Code examples
|
||||
|
||||
:code_impact: delete
|
||||
|
||||
include::../../common/fix/code-rationale.adoc[]
|
||||
|
||||
==== Noncompliant code example
|
||||
|
||||
[source,kotlin,diff-id=1,diff-type=noncompliant]
|
||||
----
|
||||
@Controller
|
||||
class ExampleController {
|
||||
companion object {
|
||||
private const val TARGET_DIRECTORY = "/path/to/target/directory/"
|
||||
}
|
||||
|
||||
@GetMapping("/delete")
|
||||
fun delete(@RequestParam("filename") filename: String) {
|
||||
val file = File(TARGET_DIRECTORY + filename)
|
||||
file.delete()
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
[source,kotlin,diff-id=1,diff-type=compliant]
|
||||
----
|
||||
@Controller
|
||||
class ExampleController {
|
||||
companion object {
|
||||
private const val TARGET_DIRECTORY = "/path/to/target/directory/"
|
||||
private val TARGET_PATH = File(TARGET_DIRECTORY).toPath().normalize()
|
||||
}
|
||||
|
||||
@GetMapping("/delete")
|
||||
fun delete(@RequestParam("filename") filename: String) {
|
||||
val file = File(TARGET_PATH.toString() + filename)
|
||||
if (!file.toPath().normalize().startsWith(TARGET_PATH)) {
|
||||
throw IOException("Entry is outside of the target directory")
|
||||
}
|
||||
file.delete()
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
=== How does this work?
|
||||
|
||||
:canonicalization_function: java.io.File.getCanonicalPath
|
||||
|
||||
include::../../common/fix/self-validation.adoc[]
|
||||
|
||||
=== Pitfalls
|
||||
|
||||
include::../../common/pitfalls/partial-path-traversal.adoc[]
|
||||
|
||||
For example, the following code is vulnerable to partial path injection. Note
|
||||
that the string `targetDirectory` does not end with a path separator:
|
||||
|
||||
|
||||
[source, kotlin]
|
||||
----
|
||||
companion object {
|
||||
private val targetDirectory: String = "/Users/John"
|
||||
}
|
||||
|
||||
@GetMapping("/endpoint")
|
||||
fun endpoint(@RequestParam("folder") file: File) {
|
||||
val canonicalizedFileName = file.getCanonicalPath()
|
||||
if (!canonicalizedFileName .startsWith(targetDirectory)) {
|
||||
throw IOException("Entry is outside of the target directory");
|
||||
}
|
||||
file.delete()
|
||||
}
|
||||
----
|
||||
|
||||
This check can be bypassed because `"/Users/Johnny".startsWith("/Users/John")`
|
||||
returns `true`. Thus, for validation, `"/Users/John"` should actually be
|
||||
`"/Users/John/"`.
|
||||
|
||||
**Warning**: Some functions, such as `.getCanonicalPath`, remove the
|
||||
terminating path separator in their return value. +
|
||||
The validation code should be tested to ensure that it cannot be impacted by this
|
||||
issue.
|
||||
|
||||
https://github.com/aws/aws-sdk-java/security/advisories/GHSA-c28r-hw5m-5gv3[Here is a real-life example of this vulnerability.]
|
||||
|
||||
|
||||
:joining_docs: https://docs.oracle.com/javase/8/docs/api/java/nio/file/Path.html
|
||||
:joining_func: java.nio.file.Path.resolve
|
||||
|
||||
include::../../common/pitfalls/oob-specific-path-joining.adoc[]
|
33
rules/S2083/kotlin/metadata.json
Normal file
33
rules/S2083/kotlin/metadata.json
Normal file
@ -0,0 +1,33 @@
|
||||
{
|
||||
"securityStandards": {
|
||||
"CWE": [
|
||||
20,
|
||||
22
|
||||
],
|
||||
"OWASP": [
|
||||
"A5",
|
||||
"A1"
|
||||
],
|
||||
"OWASP Top 10 2021": [
|
||||
"A1",
|
||||
"A3"
|
||||
],
|
||||
"OWASP Mobile Top 10 2024": [
|
||||
"M4"
|
||||
],
|
||||
"PCI DSS 3.2": [
|
||||
"6.5.8"
|
||||
],
|
||||
"PCI DSS 4.0": [
|
||||
"6.2.4"
|
||||
],
|
||||
"ASVS 4.0": [
|
||||
"12.3.1",
|
||||
"5.1.3",
|
||||
"5.1.4"
|
||||
],
|
||||
"STIG ASD_V5R3": [
|
||||
"V-222609"
|
||||
]
|
||||
}
|
||||
}
|
29
rules/S2083/kotlin/rule.adoc
Normal file
29
rules/S2083/kotlin/rule.adoc
Normal file
@ -0,0 +1,29 @@
|
||||
== Why is this an issue?
|
||||
|
||||
include::../rationale.adoc[]
|
||||
|
||||
include::../impact.adoc[]
|
||||
|
||||
// How to fix it section
|
||||
|
||||
include::how-to-fix-it/java-io-api.adoc[]
|
||||
|
||||
== Resources
|
||||
|
||||
include::../common/resources/standards-mobile.adoc[]
|
||||
|
||||
ifdef::env-github,rspecator-view[]
|
||||
|
||||
'''
|
||||
== Implementation Specification
|
||||
(visible only on this page)
|
||||
|
||||
include::../message.adoc[]
|
||||
|
||||
'''
|
||||
== Comments And Links
|
||||
(visible only on this page)
|
||||
|
||||
include::../comments-and-links.adoc[]
|
||||
|
||||
endif::env-github,rspecator-view[]
|
@ -1,4 +1,4 @@
|
||||
== How to fix it in Java SE
|
||||
== How to fix it in Java I/O API
|
||||
|
||||
=== Code examples
|
||||
|
@ -4,7 +4,7 @@ include::../rationale.adoc[]
|
||||
|
||||
include::../impact.adoc[]
|
||||
|
||||
include::how-to-fix-it/java-se.adoc[]
|
||||
include::how-to-fix-it/java-io-api.adoc[]
|
||||
|
||||
== Resources
|
||||
|
||||
|
90
rules/S6096/kotlin/how-to-fix-it/java-io-api.adoc
Normal file
90
rules/S6096/kotlin/how-to-fix-it/java-io-api.adoc
Normal file
@ -0,0 +1,90 @@
|
||||
== How to fix it in Java I/O API
|
||||
|
||||
=== Code examples
|
||||
|
||||
:canonicalization_function1: java.io.File.getCanonicalFile
|
||||
:canonicalization_function2: java.io.File.getCanonicalPath
|
||||
|
||||
include::../../common/fix/code-rationale.adoc[]
|
||||
|
||||
==== Noncompliant code example
|
||||
|
||||
[source,kotlin,diff-id=1,diff-type=noncompliant]
|
||||
----
|
||||
class Example {
|
||||
companion object {
|
||||
private const val TARGET_DIRECTORY = "/example/directory/"
|
||||
}
|
||||
fun extractEntry(zipFile: ZipFile) {
|
||||
val entries = zipFile.entries()
|
||||
val entry = entries.nextElement()
|
||||
val inputStream = zipFile.getInputStream(entry)
|
||||
val file = File(TARGET_DIRECTORY + entry.name)
|
||||
inputStream.copyTo(file.outputStream())
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
[source,kotlin,diff-id=1,diff-type=compliant]
|
||||
----
|
||||
class Example {
|
||||
companion object {
|
||||
private const val TARGET_DIRECTORY = "/example/directory/"
|
||||
}
|
||||
fun extractEntry(zipFile: ZipFile) {
|
||||
val entries = zipFile.entries()
|
||||
val entry = entries.nextElement()
|
||||
val inputStream = zipFile.getInputStream(entry)
|
||||
val file = File(TARGET_DIRECTORY + entry.name)
|
||||
val canonicalDestinationPath = file.canonicalPath
|
||||
if (canonicalDestinationPath.startsWith(TARGET_DIRECTORY)) {
|
||||
inputStream.copyTo(file.outputStream())
|
||||
}
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
=== How does this work?
|
||||
|
||||
include::../../common/fix/how-does-this-work.adoc[]
|
||||
|
||||
=== Pitfalls
|
||||
|
||||
include::../../common/pitfalls/partial-path-traversal.adoc[]
|
||||
|
||||
For example, the following code is vulnerable to partial path injection. Note
|
||||
that the string `targetDirectory` does not end with a path separator:
|
||||
|
||||
|
||||
[source, kotlin]
|
||||
----
|
||||
companion object {
|
||||
private const val targetDirectory = "/Users/John"
|
||||
}
|
||||
|
||||
fun ExtractEntry(zipFile: ZipFile) {
|
||||
val entries = zipFile.entries()
|
||||
val entry = entries.nextElement()
|
||||
val inputStream = zipFile.getInputStream(entry)
|
||||
|
||||
val file = File(entry.name)
|
||||
|
||||
val canonicalDestinationPath = file.canonicalPath
|
||||
if (canonicalDestinationPath.startsWith(targetDirectory)) {
|
||||
Files.copy(inputStream, file.toPath(), StandardCopyOption.REPLACE_EXISTING, LinkOption.NOFOLLOW_LINKS)
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
This check can be bypassed because `"/Users/Johnny".startsWith("/Users/John")`
|
||||
returns `true`. Thus, for validation, `"/Users/John"` should actually be
|
||||
`"/Users/John/"`.
|
||||
|
||||
**Warning**: Some functions, such as `.getCanonicalPath`, remove the
|
||||
terminating path separator in their return value. +
|
||||
The validation code should be tested to ensure that it cannot be impacted by this
|
||||
issue.
|
||||
|
||||
https://github.com/aws/aws-sdk-java/security/advisories/GHSA-c28r-hw5m-5gv3[Here is a real-life example of this vulnerability.]
|
34
rules/S6096/kotlin/metadata.json
Normal file
34
rules/S6096/kotlin/metadata.json
Normal file
@ -0,0 +1,34 @@
|
||||
{
|
||||
"securityStandards": {
|
||||
"CWE": [
|
||||
20,
|
||||
22
|
||||
],
|
||||
"OWASP": [
|
||||
"A5",
|
||||
"A1"
|
||||
],
|
||||
"OWASP Top 10 2021": [
|
||||
"A1",
|
||||
"A3"
|
||||
],
|
||||
"OWASP Mobile Top 10 2024": [
|
||||
"M4"
|
||||
],
|
||||
"PCI DSS 3.2": [
|
||||
"6.5.1",
|
||||
"6.5.8"
|
||||
],
|
||||
"PCI DSS 4.0": [
|
||||
"6.2.4"
|
||||
],
|
||||
"ASVS 4.0": [
|
||||
"12.3.4",
|
||||
"5.1.3",
|
||||
"5.1.4"
|
||||
],
|
||||
"STIG ASD_V5R3": [
|
||||
"V-222609"
|
||||
]
|
||||
}
|
||||
}
|
23
rules/S6096/kotlin/rule.adoc
Normal file
23
rules/S6096/kotlin/rule.adoc
Normal file
@ -0,0 +1,23 @@
|
||||
== Why is this an issue?
|
||||
|
||||
include::../rationale.adoc[]
|
||||
|
||||
include::../impact.adoc[]
|
||||
|
||||
include::how-to-fix-it/java-io-api.adoc[]
|
||||
|
||||
== Resources
|
||||
|
||||
include::../common/resources/articles.adoc[]
|
||||
|
||||
include::../common/resources/standards-mobile.adoc[]
|
||||
|
||||
ifdef::env-github,rspecator-view[]
|
||||
|
||||
'''
|
||||
== Implementation Specification
|
||||
(visible only on this page)
|
||||
|
||||
include::../message.adoc[]
|
||||
|
||||
endif::env-github,rspecator-view[]
|
@ -5,3 +5,6 @@
|
||||
* OWASP - https://owasp.org/www-project-top-ten/2017/A7_2017-Cross-Site_Scripting_(XSS)[Top 10 2017 Category A7 - Cross-Site Scripting (XSS)]
|
||||
* OWASP - https://owasp.org/www-project-mobile-top-10/2023-risks/m8-security-misconfiguration[Mobile Top 10 2024 Category M8 - Security Misconfiguration]
|
||||
* CWE - https://cwe.mitre.org/data/definitions/79[CWE-79 - Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')]
|
||||
|
||||
=== Related rules
|
||||
* S7409 - Exposing Java objects through JavaScript interfaces is security-sensitive
|
||||
|
@ -1,6 +1,6 @@
|
||||
== Ask Yourself Whether
|
||||
|
||||
* No local files have to be accessed by the Webview.
|
||||
* The WebView contains untrusted data that could cause harm when rendered.
|
||||
* You open files that may be created or altered by external sources.
|
||||
* You open arbitrary URLs from external sources.
|
||||
|
||||
There is a risk if you answered yes to any of those questions.
|
||||
There is a risk if you answered yes to any of these questions.
|
||||
|
@ -1,7 +1,7 @@
|
||||
WebViews can be used to display web content as part of a mobile application. A
|
||||
browser engine is used to render and display the content. Like a web
|
||||
application, a mobile application that uses WebViews can be vulnerable to
|
||||
Cross-Site Scripting if untrusted code is rendered.
|
||||
Exposing the Android file system to WebViews is security-sensitive.
|
||||
|
||||
If malicious JavaScript code in a WebView is executed this can leak the contents
|
||||
of sensitive files when access to local files is enabled.
|
||||
Granting file access to WebViews, particularly through the `file://` scheme, introduces a risk of local file inclusion
|
||||
vulnerabilities. The severity of this risk depends heavily on the specific `WebSettings` configured. Overly permissive
|
||||
settings can allow malicious scripts to access a wide range of local files, potentially exposing sensitive data such as
|
||||
Personally Identifiable Information (PII) or private application data, leading to data breaches and other security
|
||||
compromises.
|
||||
|
@ -8,26 +8,66 @@ include::../recommended.adoc[]
|
||||
|
||||
[source,kotlin]
|
||||
----
|
||||
import android.webkit.WebView
|
||||
|
||||
val webView: WebView = findViewById(R.id.webview)
|
||||
webView.getSettings().setAllowContentAccess(true) // Sensitive
|
||||
webView.getSettings().setAllowFileAccess(true) // Sensitive
|
||||
AndroidView(
|
||||
factory = { context ->
|
||||
WebView(context).apply {
|
||||
webViewClient = WebViewClient()
|
||||
settings.apply {
|
||||
allowFileAccess = true // Sensitive
|
||||
allowFileAccessFromFileURLs = true // Sensitive
|
||||
allowUniversalAccessFromFileURLs = true // Sensitive
|
||||
allowContentAccess = true // Sensitive
|
||||
}
|
||||
loadUrl("file:///android_asset/example.html")
|
||||
}
|
||||
}
|
||||
)
|
||||
----
|
||||
|
||||
== Compliant Solution
|
||||
|
||||
[source,kotlin]
|
||||
----
|
||||
import android.webkit.WebView
|
||||
AndroidView(
|
||||
factory = { context ->
|
||||
val webView = WebView(context)
|
||||
val assetLoader = WebViewAssetLoader.Builder()
|
||||
.addPathHandler("/assets/", WebViewAssetLoader.AssetsPathHandler(context))
|
||||
.build()
|
||||
|
||||
val webView: WebView = findViewById(R.id.webview)
|
||||
webView.getSettings().setAllowContentAccess(false)
|
||||
webView.getSettings().setAllowFileAccess(false)
|
||||
webView.webViewClient = object : WebViewClient() {
|
||||
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
override fun shouldInterceptRequest(view: WebView?, request: WebResourceRequest): WebResourceResponse? {
|
||||
return assetLoader.shouldInterceptRequest(request.url)
|
||||
}
|
||||
|
||||
@Suppress("deprecation")
|
||||
override fun shouldInterceptRequest(view: WebView?, url: String?): WebResourceResponse? {
|
||||
return assetLoader.shouldInterceptRequest(Uri.parse(url))
|
||||
}
|
||||
}
|
||||
|
||||
webView.settings.apply {
|
||||
allowFileAccess = false
|
||||
allowFileAccessFromFileURLs = false
|
||||
allowUniversalAccessFromFileURLs = false
|
||||
allowContentAccess = false
|
||||
}
|
||||
|
||||
webView.loadUrl("https://appassets.androidplatform.net/assets/example.html")
|
||||
webView
|
||||
}
|
||||
)
|
||||
----
|
||||
|
||||
include::../see.adoc[]
|
||||
The compliant solution uses `WebViewAssetLoader` to load local files instead of directly accessing them via `file://`
|
||||
URLs. This approach serves assets over a secure `https://appassets.androidplatform.net` URL, effectively isolating the
|
||||
WebView from the local file system.
|
||||
|
||||
The file access settings are disabled by default in modern Android versions. To prevent possible security issues in
|
||||
`Build.VERSION_CODES.Q` and earlier, it is still recommended to explicitly set those values to false.
|
||||
|
||||
include::../see.adoc[]
|
||||
|
||||
ifdef::env-github,rspecator-view[]
|
||||
|
||||
|
@ -26,8 +26,8 @@
|
||||
79
|
||||
],
|
||||
"OWASP": [
|
||||
"A6",
|
||||
"A7"
|
||||
"A3",
|
||||
"A6"
|
||||
],
|
||||
"MASVS": [
|
||||
"MSTG-PLATFORM-2"
|
||||
@ -36,7 +36,7 @@
|
||||
"M8"
|
||||
],
|
||||
"OWASP Top 10 2021": [
|
||||
"A3"
|
||||
"A1"
|
||||
],
|
||||
"PCI DSS 3.2": [
|
||||
"6.5.1",
|
||||
@ -53,4 +53,4 @@
|
||||
"Sonar way"
|
||||
],
|
||||
"quickfix": "unknown"
|
||||
}
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
== Recommended Secure Coding Practices
|
||||
|
||||
It is recommended to disable access to local files for WebViews unless it is
|
||||
necessary. In the case of a successful attack through a Cross-Site Scripting
|
||||
vulnerability the attackers attack surface decreases drastically if no files
|
||||
can be read out.
|
||||
Avoid opening `file://` URLs from external sources in WebView components. If your application accepts arbitrary URLs
|
||||
from external sources, do not enable this functionality. Instead, utilize `androidx.webkit.WebViewAssetLoader` to access
|
||||
files, including assets and resources, via `http(s)://` schemes.
|
||||
|
||||
For enhanced security, ensure that the options to load `file://` URLs are explicitly set to false.
|
||||
|
@ -1,7 +1,9 @@
|
||||
== See
|
||||
|
||||
* OWASP - https://owasp.org/Top10/A03_2021-Injection/[Top 10 2021 Category A3 - Injection]
|
||||
* OWASP - https://owasp.org/Top10/A01_2021-Broken_Access_Control/[Top 10 2021 Category A1 - Broken Access Control]
|
||||
* OWASP - https://owasp.org/www-project-top-ten/2017/A3_2017-Sensitive_Data_Exposure[Top 10 2017 Category A3 - Sensitive Data Exposure]
|
||||
* OWASP - https://owasp.org/www-project-top-ten/2017/A6_2017-Security_Misconfiguration[Top 10 2017 Category A6 - Security Misconfiguration]
|
||||
* OWASP - https://owasp.org/www-project-top-ten/2017/A7_2017-Cross-Site_Scripting_(XSS)[Top 10 2017 Category A7 - Cross-Site Scripting (XSS)]
|
||||
* OWASP - https://owasp.org/www-project-mobile-top-10/2023-risks/m8-security-misconfiguration[Mobile Top 10 2024 Category M8 - Security Misconfiguration]
|
||||
* OWASP - https://mas.owasp.org/checklists/MASVS-PLATFORM/[Mobile AppSec Verification Standard - Platform Interaction Requirements]
|
||||
* CWE - https://cwe.mitre.org/data/definitions/79[CWE-79 - Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')]
|
||||
* Android Documentation - https://developer.android.com/privacy-and-security/risks/webview-unsafe-file-inclusion[WebViews - Unsafe File Inclusion]
|
||||
|
@ -7,7 +7,7 @@
|
||||
},
|
||||
"attribute": "COMPLETE"
|
||||
},
|
||||
"status": "ready",
|
||||
"status": "closed",
|
||||
"remediation": {
|
||||
"func": "Constant\/Issue",
|
||||
"constantCost": "30min"
|
||||
@ -43,4 +43,4 @@
|
||||
"defaultQualityProfiles": [
|
||||
"Sonar way"
|
||||
]
|
||||
}
|
||||
}
|
@ -1,2 +1,3 @@
|
||||
{
|
||||
}
|
||||
"status": "closed"
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"title": "Exposing Java interfaces in WebViews is security-sensitive",
|
||||
"title": "Exposing Java objects through JavaScript interfaces is security-sensitive",
|
||||
"type": "SECURITY_HOTSPOT",
|
||||
"status": "ready",
|
||||
"remediation": {
|
||||
|
@ -1,15 +1,15 @@
|
||||
Using Javascript interfaces in WebViews is unsafe as it allows JavaScript to invoke Java methods,
|
||||
potentially giving attackers access to data or sensitive app functionality. WebViews might include
|
||||
untrusted sources such as third-party iframes, making this functionality particularly risky. As
|
||||
Javascript interfaces are passed to every frame in the WebView, those iframes are also able to
|
||||
access the exposed Java methods.
|
||||
Using JavaScript interfaces in WebViews to expose Java objects is unsafe. Doing so allows JavaScript
|
||||
to invoke Java methods, potentially giving attackers access to data or sensitive app functionality.
|
||||
WebViews might include untrusted sources such as third-party iframes, making this functionality
|
||||
particularly risky. As JavaScript interfaces are passed to every frame in the WebView, those iframes
|
||||
are also able to access the exposed Java object.
|
||||
|
||||
== Ask Yourself Whether
|
||||
|
||||
* The content in the WebView is fully trusted and secure.
|
||||
* Potentially untrusted iframes could be loaded in the WebView.
|
||||
* The Javascript interface has to be exposed for the entire lifecycle of the WebView.
|
||||
* The exposed Java methods will accept input from potentially untrusted sources.
|
||||
* The JavaScript interface has to be exposed for the entire lifecycle of the WebView.
|
||||
* The exposed Java object might be called by untrusted sources.
|
||||
|
||||
There is a risk if you answered yes to any of these questions.
|
||||
|
||||
@ -18,9 +18,9 @@ There is a risk if you answered yes to any of these questions.
|
||||
=== Disable JavaScript
|
||||
|
||||
If it is possible to disable JavaScript in the WebView, this is the most secure option. By default,
|
||||
JavaScript is disabled in a WebView, so you do not need to explicitly call
|
||||
``webSettings.setJavaScriptEnabled(true)`` in your ``WebSettings`` configuration. Of course, sometimes
|
||||
it is necessary to enable JavaScript, in which case the following recommendations should be considered.
|
||||
JavaScript is disabled in a WebView, so ``webSettings.setJavaScriptEnabled(false)`` does not need to
|
||||
be explicitly called. Of course, sometimes it is necessary to enable JavaScript, in which case the
|
||||
following recommendations should be considered.
|
||||
|
||||
=== Remove JavaScript interface when loading untrusted content
|
||||
|
||||
@ -63,7 +63,8 @@ class ExampleActivity : AppCompatActivity() {
|
||||
|
||||
== Compliant Solution
|
||||
|
||||
The most secure option is to disable JavaScript entirely.
|
||||
The most secure option is to disable JavaScript entirely. S6362 further explains why it should not be enabled
|
||||
unless absolutely necessary.
|
||||
|
||||
[source,kotlin]
|
||||
----
|
||||
@ -96,7 +97,8 @@ class ExampleActivity : AppCompatActivity() {
|
||||
}
|
||||
----
|
||||
|
||||
If a JavaScript bridge must be used, consider using ``WebViewCompat.addWebMessageListener`` instead. This allows you to restrict the origins that can send messages to the JavaScript bridge.
|
||||
If a JavaScript bridge must be used, consider using ``WebViewCompat.addWebMessageListener`` instead. This allows you to restrict
|
||||
the origins that can send messages to the JavaScript bridge.
|
||||
|
||||
[source,kotlin]
|
||||
----
|
||||
@ -135,3 +137,6 @@ class ExampleActivity : AppCompatActivity() {
|
||||
* OWASP - https://owasp.org/www-project-mobile-top-10/2023-risks/m4-insufficient-input-output-validation.html[Mobile Top 10 2024 Category M4 - Insufficient Input/Output Validation]
|
||||
* OWASP - https://owasp.org/www-project-mobile-top-10/2023-risks/m8-security-misconfiguration.html[Mobile Top 10 2024 Category M8 - Security Misconfiguration]
|
||||
* CWE - https://cwe.mitre.org/data/definitions/79[CWE-79 - Improper Neutralization of Input During Web Page Generation]
|
||||
|
||||
=== Related rules
|
||||
* S6362 - Enabling JavaScript support for WebViews is security-sensitive
|
||||
|
Loading…
x
Reference in New Issue
Block a user