-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Added/Updated Android Network Knowledge, Test and Demo #3617
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
125d8f2
7c50657
8e2a7ed
d60a3df
9f0dbee
61e84f1
d499f23
099da00
f196de2
b93f969
3ad66e2
b2c9aea
7b1e6a4
69cc772
031bb59
6bf5d9f
ec6f887
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| --- | ||
| title: No Networking in Native Code | ||
| alias: no-networking-in-native-code | ||
| id: MASTG-BEST-0028 | ||
| platform: android | ||
| knowledge: [MASTG-KNOW-0109] | ||
| --- | ||
|
|
||
| Use the Java/Kotlin layer for networking only. | ||
|
|
||
| The @MASTG-KNOW-0109 provide libraries which are secured by the @MASTG-KNOW-0014. | ||
|
|
||
| As they come with the Android Operating System, the app developer does not need to provide these libraries. In order to make sure, that the libraries are secure, it is recommended testing if the OS is up to date and not affected by known vulnerabilities (@MASTG-TEST-0245). | ||
|
|
||
| ## If Native Networking Is Necessary | ||
|
|
||
| If you develop native code using the [Android Native Development Kit (NDK)](https://developer.android.com/ndk), you will not have access to high level network libraries. | ||
|
|
||
| You, or any networking library you use, can still directly use POSIX sockets. However, @MASTG-KNOW-0014 will not apply automatically. | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Android allows this by giving apps the possibility to directly use low level Java or POSIX sockets for networking. However in case of not using the high level Java/Kotlin networking APIs, @MASTG-KNOW-0014 will not be able to enforce limitations such as blocking clear text traffic. |
||
|
|
||
| Some applications, like games or streaming apps, require low latency network connections. Hence they often provide their own native network stack. | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Move this sentence above the previous sentence. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would move this sentence above the previous one |
||
|
|
||
| In this case, the developer is responsible to make sure the libraries are to date (@MASTG-TEST-0274) and [configured securely](../Document/0x04f-Testing-Network-Communication.md#verifying-the-tls-settings). | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| --- | ||
| platform: android | ||
| title: Usage of Clear Text Network Protocols | ||
| id: MASTG-DEMO-0082 | ||
| code: [kotlin] | ||
| test: MASTG-TEST-0238 | ||
| --- | ||
|
|
||
| ## Sample | ||
|
|
||
| This sample creates insecure and secure URIs using the following Android API: | ||
|
|
||
| - `java.net.URL` | ||
| - `java.net.URI` | ||
| - `android.net.Uri` | ||
| - `android.media.MediaPlayer` | ||
|
|
||
| The following URI schemes are used in this demo: | ||
|
|
||
| ```kotlin | ||
| data class Schemes( | ||
| val insecure: String, | ||
| val secure: String | ||
| ) | ||
|
|
||
| val schemes = listOf( | ||
| Schemes("http", "https"), | ||
| Schemes("ws", "wss"), | ||
| Schemes("sip", "sips"), | ||
| Schemes("ldap", "ldaps"), | ||
| Schemes("ftp", "ftps"), | ||
| Schemes("rtsp", "rtsps"), | ||
| Schemes("stun", "stuns") | ||
| ) | ||
| ``` | ||
|
|
||
| The demo does not really load the remote resources. If these URIs are used, data could be sent in clear text over the network. However, it may be that @MASTG-KNOW-0014 prohibits the connection setup. | ||
|
|
||
| {{ MastgTest.kt }} | ||
|
|
||
| ### Steps | ||
|
|
||
| 1. Install the app on a device (@MASTG-TECH-0005) | ||
| 2. Make sure you have @MASTG-TOOL-0001 installed on your machine and the frida-server running on the device | ||
| 3. Run `run.sh` to spawn the app with Frida | ||
| 4. Click the **Start** button | ||
| 5. Stop the script by pressing `Ctrl+C` and/or `q` to quit the Frida CLI. | ||
|
|
||
| {{ hooks.js # run.sh }} | ||
|
|
||
| ### Observation | ||
|
|
||
| The script will generate the file `output.json` which contains information about how the functions were called. | ||
|
|
||
| ### Evaluation | ||
|
|
||
| Run `evaluate.sh output.json`. This script will parse the generated `output.json`, assess the URIs and write the identified risks to the file `evaluation.txt`. | ||
|
|
||
| {{ evaluation.txt # evaluate.sh}} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,202 @@ | ||
| package org.owasp.mastestapp | ||
|
|
||
| import android.content.Context | ||
| import android.net.Uri | ||
| import android.media.MediaPlayer | ||
| import java.net.URL | ||
| import java.net.URI | ||
|
|
||
| data class Schemes( | ||
| val insecure: String, | ||
| val secure: String | ||
| ) | ||
|
|
||
| class MastgTest(private val context: Context) { | ||
|
|
||
| fun mastgTest(): String { | ||
| val r = DemoResults("0082") | ||
| val host = "mas.owasp.org" | ||
|
|
||
| val schemes = listOf( | ||
| Schemes("http", "https"), | ||
| Schemes("ws", "wss"), | ||
| Schemes("sip", "sips"), | ||
| Schemes("ldap", "ldaps"), | ||
| Schemes("ftp", "ftps"), | ||
| Schemes("rtsp", "rtsps"), | ||
| Schemes("stun", "stuns") | ||
| ) | ||
|
|
||
| schemes.forEach { scheme -> | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This function looks a bit too long. Can you divide the tests into smaller functions, focusing on individual test cases? |
||
| val secureUri = "${scheme.secure}://$host" | ||
| val insecureUri = "${scheme.insecure}://$host" | ||
|
|
||
| // java.net.URL throws an exception if the scheme is not http, https or ftp | ||
| if( scheme.insecure == "http" || scheme.insecure == "ftp" ){ | ||
|
|
||
| // java.net.URL(String spec) | ||
| try { | ||
| val test = URL(secureUri) | ||
| print(test) | ||
| r.add(Status.PASS, "Secure URL created with $secureUri (String spec)") | ||
| } catch (e: Exception) { | ||
| r.add(Status.ERROR, e.toString()) | ||
| } | ||
| try { | ||
| URL(insecureUri) | ||
| r.add(Status.FAIL, "Insecure URL created with $insecureUri (String spec)") | ||
| } catch (e: Exception) { | ||
| r.add(Status.ERROR, e.toString()) | ||
| } | ||
|
|
||
| // java.net.URL(String protocol, String host, int port, String file) | ||
| try { | ||
| URL(scheme.secure, host, 443, "/") | ||
| r.add(Status.PASS, "Secure URL created with ${scheme.secure}://$host:443/ (String protocol, String host, int port, String file)") | ||
| } catch (e: Exception) { | ||
| r.add(Status.ERROR, e.toString()) | ||
| } | ||
| try { | ||
| URL(scheme.insecure, host, 80, "/") | ||
| r.add(Status.FAIL, "Insecure URL created with ${scheme.insecure}://$host:80/ (String protocol, String host, int port, String file)") | ||
| } catch (e: Exception) { | ||
| r.add(Status.ERROR, e.toString()) | ||
| } | ||
|
|
||
| // java.net.URL(String protocol, String host, int port, String file, URLStreamHandler handler) | ||
| try { | ||
| URL(scheme.secure, host, 443, "/", null) | ||
| r.add(Status.PASS, "Secure URL created with ${scheme.secure}://$host:443/ (String protocol, String host, int port, String file, URLStreamHandler handler)") | ||
| } catch (e: Exception) { | ||
| r.add(Status.ERROR, e.toString()) | ||
| } | ||
| try { | ||
| URL(scheme.insecure, host, 80, "/", null) | ||
| r.add(Status.FAIL, "Insecure URL created with ${scheme.insecure}://$host:80/ (String protocol, String host, int port, String file, URLStreamHandler handler)") | ||
| } catch (e: Exception) { | ||
| r.add(Status.ERROR, e.toString()) | ||
| } | ||
|
|
||
| // java.net.URL(String protocol, String host, String file) | ||
| try { | ||
| URL(scheme.secure, host, "/") | ||
| r.add(Status.PASS, "Secure URL created with ${scheme.secure}://$host/ (String protocol, String host, String file)") | ||
| } catch (e: Exception) { | ||
| r.add(Status.ERROR, e.toString()) | ||
| } | ||
| try { | ||
| URL(scheme.insecure, host, "/") | ||
| r.add(Status.FAIL, "Insecure URL created with ${scheme.insecure}://$host/ (String protocol, String host, String file)") | ||
| } catch (e: Exception) { | ||
| r.add(Status.ERROR, e.toString()) | ||
| } | ||
| } | ||
|
|
||
|
|
||
| // java.net.URI(String spec) | ||
| try { | ||
| URI(secureUri) | ||
| r.add(Status.PASS, "Secure URI created with $secureUri (String spec)") | ||
| } catch (e: Exception) { | ||
| r.add(Status.ERROR, e.toString()) | ||
| } | ||
| try { | ||
| URI(insecureUri) | ||
| r.add(Status.FAIL, "Insecure URI created with $insecureUri (String spec)") | ||
| } catch (e: Exception) { | ||
| r.add(Status.ERROR, e.toString()) | ||
| } | ||
|
|
||
| // java.net.URI(String scheme, String ssp, String fragment) | ||
| try { | ||
| URI(scheme.secure, "//$host/", null) | ||
| r.add(Status.PASS, "Secure URI created with ${scheme.secure}://$host/ (String scheme, String ssp, String fragment)") | ||
| } catch (e: Exception) { | ||
| r.add(Status.ERROR, e.toString()) | ||
| } | ||
| try { | ||
| URI(scheme.insecure, "//$host/", null) | ||
| r.add(Status.FAIL, "Insecure URI created with ${scheme.insecure}://$host/ (String scheme, String ssp, String fragment)") | ||
| } catch (e: Exception) { | ||
| r.add(Status.ERROR, e.toString()) | ||
| } | ||
|
|
||
| // java.net.URI(String scheme, String host, String path, String fragment) | ||
| try { | ||
| URI(scheme.secure, host, "/", null) | ||
| r.add(Status.PASS, "Secure URI created with ${scheme.secure}://$host/ (String scheme, String host, String path, String fragment)") | ||
| } catch (e: Exception) { | ||
| r.add(Status.ERROR, e.toString()) | ||
| } | ||
| try { | ||
| URI(scheme.insecure, host, "/", null) | ||
| r.add(Status.FAIL, "Insecure URI created with ${scheme.insecure}://$host/ (String scheme, String host, String path, String fragment)") | ||
| } catch (e: Exception) { | ||
| r.add(Status.ERROR, e.toString()) | ||
| } | ||
|
|
||
| // java.net.URI(String scheme, String authority, String path, String query, String fragment) | ||
| try { | ||
| URI(scheme.secure, host, "/", null, null) | ||
| r.add(Status.PASS, "Secure URI created with ${scheme.secure}://$host/ (String scheme, String authority, String path, String query, String fragment)") | ||
| } catch (e: Exception) { | ||
| r.add(Status.ERROR, e.toString()) | ||
| } | ||
| try { | ||
| URI(scheme.insecure, host, "/", null, null) | ||
| r.add(Status.FAIL, "Insecure URI created with ${scheme.insecure}://$host/ (String scheme, String authority, String path, String query, String fragment)") | ||
| } catch (e: Exception) { | ||
| r.add(Status.ERROR, e.toString()) | ||
| } | ||
|
|
||
| // android.net.Uri.parse(String uriString) | ||
| try { | ||
| Uri.parse(secureUri) | ||
| r.add(Status.PASS, "Secure Uri created with $secureUri (Uri.parse)") | ||
| } catch (e: Exception) { | ||
| r.add(Status.ERROR, e.toString()) | ||
| } | ||
| try { | ||
| Uri.parse(insecureUri) | ||
| r.add(Status.FAIL, "Insecure Uri created with $insecureUri (Uri.parse)") | ||
| } catch (e: Exception) { | ||
| r.add(Status.ERROR, e.toString()) | ||
| } | ||
|
|
||
| // android.net.Uri.Builder.scheme(String scheme) | ||
| try { | ||
| Uri.Builder().scheme(scheme.secure).authority(host).build() | ||
| r.add(Status.PASS, "Secure Uri created with ${scheme.secure}://$host (Uri.Builder.scheme)") | ||
| } catch (e: Exception) { | ||
| r.add(Status.ERROR, e.toString()) | ||
| } | ||
| try { | ||
| Uri.Builder().scheme(scheme.insecure).authority(host).build() | ||
| r.add(Status.FAIL, "Insecure Uri created with ${scheme.insecure}://$host (Uri.Builder.scheme)") | ||
| } catch (e: Exception) { | ||
| r.add(Status.ERROR, e.toString()) | ||
| } | ||
|
|
||
| // android.media.MediaPlayer.setDataSource(String path) | ||
| try { | ||
| val mediaPlayer = MediaPlayer() | ||
| mediaPlayer.setDataSource(secureUri) | ||
| r.add(Status.PASS, "Secure data source set with $secureUri (MediaPlayer.setDataSource)") | ||
| mediaPlayer.release() | ||
| } catch (e: Exception) { | ||
| r.add(Status.ERROR, e.toString()) | ||
| } | ||
|
|
||
| try { | ||
| val mediaPlayer2 = MediaPlayer() | ||
| mediaPlayer2.setDataSource(insecureUri) | ||
| r.add(Status.FAIL, "Insecure data source set with $insecureUri (MediaPlayer.setDataSource)") | ||
| mediaPlayer2.release() | ||
| } catch (e: Exception) { | ||
| r.add(Status.ERROR, e.toString()) | ||
| } | ||
| } | ||
|
|
||
| return r.toJson() | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| #!/bin/bash | ||
|
|
||
| # Define insecure URI schemes | ||
| insecure_schemes=("http" "ws" "sip" "ldap" "ftp" "rtsp" "stun") | ||
|
|
||
| # Read the JSONC file and process each JSON object | ||
| jq -c '.' "$1" 2>/dev/null | while IFS= read -r line; do | ||
| # Extract class and inputParameters | ||
| class=$(echo "$line" | jq -r '.class') | ||
|
|
||
| # Check each inputParameter value | ||
| echo "$line" | jq -r '.inputParameters[]?.value' 2>/dev/null | while IFS= read -r value; do | ||
| # Skip if value is "void" or empty | ||
| if [[ "$value" == "void" || -z "$value" ]]; then | ||
| continue | ||
| fi | ||
|
|
||
| # Check if value starts with any insecure scheme | ||
| for scheme in "${insecure_schemes[@]}"; do | ||
| if [[ "$value" == "$scheme"* ]]; then | ||
| # Extract scheme name without colon | ||
| scheme_name="${scheme}" | ||
| echo "[!] $class was used to create an insecure URI with the scheme '$scheme_name'" | ||
| break | ||
| fi | ||
| done | ||
| done | ||
| done | sort | uniq > evaluation.txt |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| [!] android.media.MediaPlayer was used to create an insecure URI with the scheme 'ftp' | ||
| [!] android.media.MediaPlayer was used to create an insecure URI with the scheme 'http' | ||
| [!] android.media.MediaPlayer was used to create an insecure URI with the scheme 'ldap' | ||
| [!] android.media.MediaPlayer was used to create an insecure URI with the scheme 'rtsp' | ||
| [!] android.media.MediaPlayer was used to create an insecure URI with the scheme 'sip' | ||
| [!] android.media.MediaPlayer was used to create an insecure URI with the scheme 'stun' | ||
| [!] android.media.MediaPlayer was used to create an insecure URI with the scheme 'ws' | ||
| [!] android.net.Uri was used to create an insecure URI with the scheme 'ftp' | ||
| [!] android.net.Uri was used to create an insecure URI with the scheme 'http' | ||
| [!] android.net.Uri was used to create an insecure URI with the scheme 'ldap' | ||
| [!] android.net.Uri was used to create an insecure URI with the scheme 'rtsp' | ||
| [!] android.net.Uri was used to create an insecure URI with the scheme 'sip' | ||
| [!] android.net.Uri was used to create an insecure URI with the scheme 'stun' | ||
| [!] android.net.Uri was used to create an insecure URI with the scheme 'ws' | ||
| [!] android.net.Uri$Builder was used to create an insecure URI with the scheme 'ftp' | ||
| [!] android.net.Uri$Builder was used to create an insecure URI with the scheme 'http' | ||
| [!] android.net.Uri$Builder was used to create an insecure URI with the scheme 'ldap' | ||
| [!] android.net.Uri$Builder was used to create an insecure URI with the scheme 'rtsp' | ||
| [!] android.net.Uri$Builder was used to create an insecure URI with the scheme 'sip' | ||
| [!] android.net.Uri$Builder was used to create an insecure URI with the scheme 'stun' | ||
| [!] android.net.Uri$Builder was used to create an insecure URI with the scheme 'ws' | ||
| [!] java.net.URI was used to create an insecure URI with the scheme 'ftp' | ||
| [!] java.net.URI was used to create an insecure URI with the scheme 'http' | ||
| [!] java.net.URI was used to create an insecure URI with the scheme 'ldap' | ||
| [!] java.net.URI was used to create an insecure URI with the scheme 'rtsp' | ||
| [!] java.net.URI was used to create an insecure URI with the scheme 'sip' | ||
| [!] java.net.URI was used to create an insecure URI with the scheme 'stun' | ||
| [!] java.net.URI was used to create an insecure URI with the scheme 'ws' | ||
| [!] java.net.URL was used to create an insecure URI with the scheme 'ftp' | ||
| [!] java.net.URL was used to create an insecure URI with the scheme 'http' |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| var target = { | ||
| category: "NETWORK", | ||
| demo: "0082", | ||
| hooks: [ | ||
| { | ||
| class: "java.net.URL", | ||
| methods: [ | ||
| "$init" | ||
| ] | ||
| }, | ||
| { | ||
| class: "java.net.URI", | ||
| methods: [ | ||
| "$init" | ||
| ] | ||
| }, | ||
| { | ||
| class: "android.net.Uri", | ||
| methods: [ | ||
| "parse" | ||
| ] | ||
| }, | ||
| { | ||
| class: "android.net.Uri$Builder", | ||
| methods: [ | ||
| "scheme" | ||
| ] | ||
| }, | ||
| { | ||
| class: "android.media.MediaPlayer", | ||
| methods: [ | ||
| "setDataSource" | ||
| ] | ||
| } | ||
| ] | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is supported in Android by directly providing POSIX sockets. However, the restrictions of the @MASTG-KNOW-0014 like the prohibited use of clear text traffic will not apply automatically.