Skip to content

Commit

Permalink
Fix mappings, fix consistency in test and risk sections (#2633)
Browse files Browse the repository at this point in the history
* fix mappings, fix consistency in test and risk sections

* fix spelling

* add Identifying Security-Relevant Contexts in Code to 4b for now and fix broken links
  • Loading branch information
cpholguera authored Jun 24, 2024
1 parent 07f7786 commit 141c719
Show file tree
Hide file tree
Showing 13 changed files with 178 additions and 46 deletions.
16 changes: 15 additions & 1 deletion Document/0x04b-Mobile-App-Security-Testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,21 @@ When no data classification policy is available, use the following list of infor
- any data whose protection is a legal obligation
- any technical data generated by the app (or its related systems) and used to protect other data or the system itself (e.g., encryption keys)

A definition of "sensitive data" must be decided before testing begins because detecting sensitive data leakage without a definition may be impossible.
A definition of "sensitive data" must be decided before testing begins because detecting sensitive data leakage without a definition may be impossible.

##### Identifying Security-Relevant Contexts in Code

When developing a mobile application, it's crucial to accurately identify and handle security-relevant contexts within the codebase. These contexts typically involve operations such as authentication, encryption, and authorization, which are often the target of security attacks. Incorrect implementation of cryptographic functions in these areas can lead to significant security vulnerabilities.

Properly distinguishing security-relevant contexts helps in minimizing false positives during security testing. False positives can divert attention from real issues and waste valuable resources. Here are some common scenarios:

- **Random Number Generation**: Using weak random number generators can be a serious security flaw in contexts like authentication or encryption key generation. However, not all uses of random numbers are security-sensitive. For instance, using a less robust random number generator for non-security purposes like shuffling a list of items in a game is generally acceptable.

- **Hashing**: Hashing is often used in security for storing passwords or ensuring data integrity. However, hashing a non-sensitive value, like a device's screen resolution for analytics, isn't a security concern.

- **Encryption vs Encoding**: A common misunderstanding is conflating encoding (like Base64) with encryption. Base64 encoding is not a secure method for protecting sensitive data as it's easily reversible. It's crucial to recognize when data requires actual encryption (for confidentiality) versus when it's being encoded for compatibility or formatting reasons (like encoding binary data into a text format for transmission). Misinterpreting encoding as a security measure can lead to overlooking actual encryption needs for sensitive data.

- **API Token Storage**: Storing API tokens or keys in plain text within the app's code or in insecure locations (like SharedPreferences on Android or UserDefaults on iOS) is a common security mistake. However, if the token is for a non-sensitive, read-only public API, this might not be a security risk. Contrast this with storing a token for a sensitive or write-access API, where improper storage would be a significant security concern.

#### Intelligence Gathering

Expand Down
2 changes: 2 additions & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ edit_uri: "" # disable edit button

nav:
- Home: index.md
- "":
- ... | MASWE/**/*.md
- MASTG:
- MASTG/index.md
- Intro:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,8 @@ Android apps sometimes use insecure pseudorandom number generators (PRNGs) such

## Observation

The output should contain a **list of locations where insecure random APIs are used**.
The output should contain a list of locations where insecure random APIs are used.

## Evaluation

Inspect the app source code using the provided location information.

The test case fails if you can find random numbers generated using those APIs that are used in security-relevant contexts.
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,8 @@ Android applications sometimes use non-random sources to generate "random" value

## Observation

The output should contain a **list of locations where non-random sources are used**.
The output should contain a list of locations where non-random sources are used.

## Evaluation

Inspect the app source code using the provided location information.

The test case fails if you can find security-relevant values, such as passwords or tokens, generated using non-random sources.
8 changes: 4 additions & 4 deletions risks/MASVS-CRYPTO/1-strong-crypto/insecure-random/risk.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ alias: insecure-random
platform: ["android", "ios"]
profiles: ["L1", "L2"]
mappings:
- masvs-v1: [MSTG-CRYPTO-6]
- masvs-v2: [MASVS-CRYPTO-1]
- cwe: [338, 337]
- android: https://developer.android.com/privacy-and-security/risks/weak-prng
masvs-v1: [MSTG-CRYPTO-6]
masvs-v2: [MASVS-CRYPTO-1]
cwe: [338, 337]
android: https://developer.android.com/privacy-and-security/risks/weak-prng
observed_examples:
- https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2013-6386
- https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2006-3419
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,7 @@ import java.util.logging.Logger

class MastgTest (private val context: Context){

fun mastgTest(): String {

// Requires: <uses-permission android:name="android.permission.INTERNET" />
fun mastgTest(): String {

val SENSITIVE_DATA = mapOf(
"precise_location_latitude" to "37.7749",
Expand Down Expand Up @@ -48,12 +46,13 @@ class MastgTest (private val context: Context){
outputStream.close()

val responseCode = httpURLConnection.responseCode
val responseContent = httpURLConnection.inputStream.bufferedReader().readText()
if (responseCode == HttpURLConnection.HTTP_OK) {
Log.d("HTTP_SUCCESS", "Successfully authenticated.")
} else {
Log.e("HTTP_ERROR", "Failed to authenticate. Response code: $responseCode")
}
result = "$responseCode\n\n$postData"
result = "$responseCode\n\n$responseContent"

} catch (e: Exception) {
e.printStackTrace()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package org.owasp.mastestapp;

import android.content.Context;
import android.util.Log;
import androidx.autofill.HintConstants;
import java.io.BufferedOutputStream;
import java.io.BufferedWriter;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import kotlin.Metadata;
import kotlin.TuplesKt;
import kotlin.collections.CollectionsKt;
import kotlin.collections.MapsKt;
import kotlin.jvm.internal.Intrinsics;
import kotlin.jvm.internal.Ref;

/* compiled from: MastgTest.kt */
@Metadata(d1 = {"\u0000\u0018\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0000\n\u0002\u0018\u0002\n\u0002\b\u0002\n\u0002\u0010\u000e\n\u0000\b\u0007\u0018\u00002\u00020\u0001B\r\u0012\u0006\u0010\u0002\u001a\u00020\u0003¢\u0006\u0002\u0010\u0004J\u0006\u0010\u0005\u001a\u00020\u0006R\u000e\u0010\u0002\u001a\u00020\u0003X\u0082\u0004¢\u0006\u0002\n\u0000¨\u0006\u0007"}, d2 = {"Lorg/owasp/mastestapp/MastgTest;", "", "context", "Landroid/content/Context;", "(Landroid/content/Context;)V", "mastgTest", "", "app_debug"}, k = 1, mv = {1, 9, 0}, xi = 48)
/* loaded from: classes4.dex */
public final class MastgTest {
public static final int $stable = 8;
private final Context context;

public MastgTest(Context context) {
Intrinsics.checkNotNullParameter(context, "context");
this.context = context;
}

/* JADX WARN: Multi-variable type inference failed */
public final String mastgTest() {
final Map SENSITIVE_DATA = MapsKt.mapOf(TuplesKt.to("precise_location_latitude", "37.7749"), TuplesKt.to("precise_location_longitude", "-122.4194"), TuplesKt.to(HintConstants.AUTOFILL_HINT_NAME, "John Doe"), TuplesKt.to("email_address", "[email protected]"), TuplesKt.to("phone_number", "+11234567890"), TuplesKt.to("credit_card_number", "1234 5678 9012 3456"));
final Ref.ObjectRef result = new Ref.ObjectRef();
result.element = "";
Thread thread = new Thread(new Runnable() { // from class: org.owasp.mastestapp.MastgTest$$ExternalSyntheticLambda0
@Override // java.lang.Runnable
public final void run() {
MastgTest.mastgTest$lambda$1(SENSITIVE_DATA, result);
}
});
thread.start();
thread.join();
return (String) result.element;
}

/* JADX INFO: Access modifiers changed from: private */
/* JADX WARN: Type inference failed for: r7v10, types: [T, java.lang.String] */
public static final void mastgTest$lambda$1(Map SENSITIVE_DATA, Ref.ObjectRef result) {
Intrinsics.checkNotNullParameter(SENSITIVE_DATA, "$SENSITIVE_DATA");
Intrinsics.checkNotNullParameter(result, "$result");
try {
URL url = new URL("https://httpbin.org/post");
URLConnection openConnection = url.openConnection();
Intrinsics.checkNotNull(openConnection, "null cannot be cast to non-null type java.net.HttpURLConnection");
HttpURLConnection httpURLConnection = (HttpURLConnection) openConnection;
httpURLConnection.setRequestMethod("POST");
httpURLConnection.setDoOutput(true);
httpURLConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
Collection destination$iv$iv = new ArrayList(SENSITIVE_DATA.size());
for (Map.Entry item$iv$iv : SENSITIVE_DATA.entrySet()) {
String key = (String) item$iv$iv.getKey();
String value = (String) item$iv$iv.getValue();
destination$iv$iv.add(URLEncoder.encode(key, "UTF-8") + '=' + URLEncoder.encode(value, "UTF-8"));
url = url;
}
String postData = CollectionsKt.joinToString$default((List) destination$iv$iv, "&", null, null, 0, null, null, 62, null);
BufferedOutputStream outputStream = new BufferedOutputStream(httpURLConnection.getOutputStream());
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream, "UTF-8"));
bufferedWriter.write(postData);
bufferedWriter.flush();
bufferedWriter.close();
outputStream.close();
int responseCode = httpURLConnection.getResponseCode();
if (responseCode == 200) {
Log.d("HTTP_SUCCESS", "Successfully authenticated.");
} else {
Log.e("HTTP_ERROR", "Failed to authenticate. Response code: " + responseCode);
}
result.element = responseCode + "\n\n" + postData;
} catch (Exception e) {
e.printStackTrace();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,36 +7,40 @@ code: [kotlin]

### Sample

{{ MastgTest.kt }}
The snippet below shows sample code that sends sensitive data over the network using the `HttpURLConnection` class. The data is sent to `https://httpbin.org/post` which is a dummy endpoint that returns the data it receives.

{{ MastgTest.kt # MastgTest_reversed.java }}

### Steps

1. Start the device, in this case, the Android emulator:
Start the device, in this case, the Android emulator:

```bash
emulator -avd Pixel_3a_API_33_arm64-v8a -writable-system
```

2. Run mitmproxy with the custom script for logging sensitive data and dump the relevant traffic to a file.
Run mitmproxy with the custom script for logging sensitive data and dump the relevant traffic to a file.

Note that the script is preconfigured with data that's already considered sensitive for this application. When running this test in a real-world scenario, you should determine what is considered [sensitive data](../../../../../../Document/0x04b-Mobile-App-Security-Testing.md#identifying-sensitive-data "Sensitive Data") based on the app's privacy policy and relevant privacy regulations. One recommended way to do this is by checking the app's privacy policy and the App Store Privacy declarations.

{{ mitm_sensitive_logger.py }}

{{ run.sh }}

3. Launch the app from Android Studio and click the button in the app.
Launch the app from Android Studio and click the button which will send the sensitive data over the network. The script will capture the network traffic and log the sensitive data.

### Observation

The script has identified several instances in the network traffic where sensitive data is sent.
The script has identified several instances of sensitive data in the network traffic.

- The first instance is a POST request to `https://httpbin.org/post` which contains the sensitive data values in the request body.
- The second instance is a response from `https://httpbin.org/post` which contains the sensitive data values in the response body.

{{ sensitive_data.log }}

### Evaluation

Review each of the reported instances.

- The first instance is a POST request to `https://httpbin.org/post` which contains the sensitive data values in the request body.
- The second instance is a response from `https://httpbin.org/post` which contains the sensitive data values in the response body.
After reviewing the captured network traffic, we can conclude that the test fails because the sensitive data is sent over the network.

This is a dummy example, but in a real-world scenario, you should determine which of the reported instances are privacy-relevant and need to be addressed.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,20 @@ prerequisites:

Attackers may capture network traffic from Android devices using an intercepting proxy, such as [OWASP ZAP](https://www.zaproxy.org/), [Burp Suite](https://portswigger.net/burp), or [mitmproxy](https://mitmproxy.org/), to analyze the data being transmitted by the app. This works even if the app uses HTTPS, as the attacker can install a custom root certificate on the Android device to decrypt the traffic. Inspecting traffic that is not encrypted with HTTPS is even easier and can be done without installing a custom root certificate for example by using [Wireshark](https://www.wireshark.org/).

The goal of this test is to verify that sensitive data is not being sent over the network, even if the traffic is encrypted. This test is especially important for apps that handle sensitive data, such as financial or health data, and should be performed in conjunction with a review of the app's privacy policy and the App Store Privacy declarations.

## Steps

1. Start the device.

2. Start [logging sensitive data from network traffic](../../../../../techniques/android/MASTG-TECH-0100.md).

3. Launch and use the app going through the various workflows while inputting sensitive data wherever you can. Especially, places where you know that will trigger network traffic.

## Observation

The **network traffic sensitive data log** including decrypted HTTPS traffic contains the sensitive data you entered in the app.
The output should contain a network traffic sensitive data log that includes the decrypted HTTPS traffic.

## Evaluation

The test case fails if you can find the sensitive data you entered in the app within the **network traffic sensitive data log** that is not stated in the App Store Privacy declarations.
The test case fails if you can find the sensitive data you entered in the app that is not stated in the App Store Privacy declarations.

Note that this test does not provide any code locations where the sensitive data is being sent over the network. In order to identify the code locations, you can use static analysis tools like [semgrep](https://semgrep.dev/) or dynamic analysis tools like [Frida](https://frida.re/).
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ alias: sensitive-data-in-network-traffic
platform: ["android", "ios"]
profiles: ["P"]
mappings:
- masvs-v1: [MSTG-NETWORK-1]
- masvs-v2: [MASVS-PRIVACY-1]
- cwe: [359]
masvs-v1: [MSTG-NETWORK-1]
masvs-v2: [MASVS-PRIVACY-1]
cwe: [359]
---

## Overview
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,13 @@ On Android platforms, logging APIs like `Log`, `Logger`, `System.out.print`, `Sy
## Steps

1. Install and run the app.

2. Navigate to the screen of the mobile app you want to analyse the log output from.

3. Execute a [method trace](https://mas.owasp.org/MASTG/techniques/android/MASTG-TECH-00xx/) by attaching to the running app, targeting logging APIs and save the output.
3. Execute a [method trace](../../../../../techniques/android/MASTG-TECH-0033.md) by attaching to the running app, targeting logging APIs and save the output.

## Observation

The **method trace output** contains a list of locations where logging APIs are used in the app for the current execution.
The output should contain a list of locations where logging APIs are used in the app for the current execution.

## Evaluation

The test case fails if you can find sensitive data being logged using those APIs.

For example, the following output leaks a key via `Log`:

```shell
Log.println_native(0, 4, "tag", "key: 12345678")
```
10 changes: 5 additions & 5 deletions risks/MASVS-STORAGE/2-prevent-data-leakage/data-in-logs/risk.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,17 @@ alias: data-in-logs
platform: ["android", "ios"]
profiles: ["L1", "L2", "P"]
mappings:
- masvs-v1: [MSTG-STORAGE-7]
- masvs-v2: [MASVS-STORAGE-2, MASVS-PRIVACY-1]
- cwe: [200, 359, 497, 532]
- android: https://developer.android.com/topic/security/risks/log-info-disclosure
masvs-v1: [MSTG-STORAGE-7]
masvs-v2: [MASVS-STORAGE-2, MASVS-PRIVACY-1]
cwe: [200, 359, 497, 532]
android: https://developer.android.com/privacy-and-security/risks/log-info-disclosure
refs:
- https://stackoverflow.com/questions/45270547/is-read-logs-a-normal-or-dangerous-android-permission
---

## Overview

Mobile apps may write [sensitive data](MASTG-THEORY-0023.md "Sensitive Data") to [logs](MASTG-THEORY-0033.md "Logs"). This may include sensitive user data, such as passwords, credit card numbers, or other personally identifiable information (PII), as well as sensitive system data, such as cryptographic keys, session tokens, or other sensitive information.
Mobile apps may write [sensitive data](../../../../Document/0x04b-Mobile-App-Security-Testing.md#identifying-sensitive-data "Sensitive Data") to logs. This may include sensitive user data, such as passwords, credit card numbers, or other personally identifiable information (PII), as well as sensitive system data, such as cryptographic keys, session tokens, or other sensitive information.

Logging all possible information is very useful at development time, especially for debugging the app. However, in production it might not always be necessary and should be prevented whenever possible to avoid any accidentally exposure to potential attackers.

Expand Down
Loading

0 comments on commit 141c719

Please sign in to comment.