Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions best-practices/MASTG-BEST-0028.md
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.

Some applications, like games or streaming apps, require low latency network connections. Hence they often provide their own native network stack.

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).
59 changes: 59 additions & 0 deletions demos/android/MASVS-NETWORK/MASTG-DEMO-0082/MASTG-DEMO-0082.md
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}}
202 changes: 202 additions & 0 deletions demos/android/MASVS-NETWORK/MASTG-DEMO-0082/MastgTest.kt
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 ->
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()
}
}
28 changes: 28 additions & 0 deletions demos/android/MASVS-NETWORK/MASTG-DEMO-0082/evaluate.sh
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
30 changes: 30 additions & 0 deletions demos/android/MASVS-NETWORK/MASTG-DEMO-0082/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'
36 changes: 36 additions & 0 deletions demos/android/MASVS-NETWORK/MASTG-DEMO-0082/hooks.js
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"
]
}
]
}
Loading