Sensible Daten, die in einem externen Speicher gespeichert sind

OWASP-Kategorie:MASVS-STORAGE: Speicher

Übersicht

Für Apps, die auf Android 10 (API 29) oder niedriger ausgerichtet sind, wird kein Geltungsbereich festgelegt Speicherplatz. Das bedeutet, dass auf alle Daten, die auf dem externen Speicher gespeichert sind, jede andere Anwendung mit der Berechtigung READ_EXTERNAL_STORAGE zugreifen kann.

Positiv beeinflussen

In Apps, die auf Android 10 (API 29) oder niedriger ausgerichtet sind, wenn sensible Daten die im externen Speicher abgelegt werden, Die Berechtigung READ_EXTERNAL_STORAGE hat Zugriff darauf. Dadurch werden schädliche um dauerhaft oder vorübergehend ohne Ton auf vertrauliche Dateien zuzugreifen im externen Speicher. Da Inhalte auf der externen Website Jede App im System kann auf den Speicher zugreifen, d. h. jede schädliche App, die deklariert außerdem die Berechtigung WRITE_EXTERNAL_STORAGE, die gespeicherte Dateien auf dem externen Speicher, z.B. um schädliche Daten einzubauen. Wenn diese schädlichen Daten in die Anwendung geladen werden, können sie dazu dienen, Nutzer zu täuschen oder sogar Code auszuführen.

Abwehrmaßnahmen

Begrenzter Speicher (Android 10 und höher)

Android 10

Für Anwendungen, die auf Android 10 ausgerichtet sind, können Entwickler den Speicher mit begrenztem Zugriff explizit aktivieren. Dies kann erreicht werden, indem der Parameter requestLegacyExternalStorage im Feld false auf AndroidManifest.xml-Datei. Bei befristetem Speicher können Apps nur auf Dateien zugreifen, die sie selbst im externen Speicher erstellt haben, oder auf Dateitypen, die mit der MediaStore API gespeichert wurden, z. B. Audio- und Videodateien. Dieses trägt zum Datenschutz und zur Sicherheit der Nutzer bei.

Android 11 und höher

Für Apps, die auf Android 11 oder höher ausgerichtet sind, erzwingt das Betriebssystem die begrenztem Speicher verwendet, d.h. die requestLegacyExternalStorage markiert und schützt automatisch Anwendungen externen Speicher vor unerwünschtem Zugriff.

Internen Speicher für sensible Daten verwenden

Unabhängig von der Android-Zielversion werden die sensiblen Daten einer App sollten immer im internen Speicher abgelegt werden. Der Zugriff auf den internen Speicher wird dank der Android-Sandbox automatisch auf die zugehörige Anwendung beschränkt. Daher kann er als sicher betrachtet werden, es sei denn, das Gerät wurde gerootet.

Vertrauliche Daten verschlüsseln

Wenn die Anwendungsfälle der Anwendung das Speichern sensibler Daten auf der externen sollten die Daten verschlüsselt sein. Ein starker Verschlüsselungsalgorithmus empfohlen, mit dem Android KeyStore, um den Schlüssel sicher zu speichern.

Im Allgemeinen wird empfohlen, alle vertraulichen Daten zu verschlüsseln, unabhängig davon, wo sie gespeichert sind.

Die Datenträgervollverschlüsselung (oder die dateibasierte Verschlüsselung Android 10) ist eine Maßnahme, die darauf abzielt, Daten vor physischem Zugriff und anderen Angriffsvektoren. Aus diesem Grund müssen Sie, um die gleiche Sicherheitsmaßnahme Daten auf externen Speichermedien zusätzlich durch den .

Integritätsprüfungen durchführen

Wenn Daten oder Code aus dem externen Speicher in die Anwendung geladen werden müssen, werden Integritätsprüfungen empfohlen, um sicherzustellen, dass keine andere Anwendung diese Daten oder diesen Code manipuliert hat. Die Hashes der Dateien sollten gespeichert werden, sicher, vorzugsweise verschlüsselt und im internen Speicher.

Kotlin

package com.example.myapplication

import java.io.BufferedInputStream
import java.io.FileInputStream
import java.io.IOException
import java.security.MessageDigest
import java.security.NoSuchAlgorithmException

object FileIntegrityChecker {
    @Throws(IOException::class, NoSuchAlgorithmException::class)
    fun getIntegrityHash(filePath: String?): String {
        val md = MessageDigest.getInstance("SHA-256") // You can choose other algorithms as needed
        val buffer = ByteArray(8192)
        var bytesRead: Int
        BufferedInputStream(FileInputStream(filePath)).use { fis ->
            while (fis.read(buffer).also { bytesRead = it } != -1) {
                md.update(buffer, 0, bytesRead)
            }

    }

    private fun bytesToHex(bytes: ByteArray): String {
        val sb = StringBuilder()
        for (b in bytes) {
            sb.append(String.format("%02x", b))
        }
        return sb.toString()
    }

    @Throws(IOException::class, NoSuchAlgorithmException::class)
    fun verifyIntegrity(filePath: String?, expectedHash: String): Boolean {
        val actualHash = getIntegrityHash(filePath)
        return actualHash == expectedHash
    }

    @Throws(Exception::class)
    @JvmStatic
    fun main(args: Array<String>) {
        val filePath = "/path/to/your/file"
        val expectedHash = "your_expected_hash_value"
        if (verifyIntegrity(filePath, expectedHash)) {
            println("File integrity is valid!")
        } else {
            println("File integrity is compromised!")
        }
    }
}

Java

package com.example.myapplication;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class FileIntegrityChecker {

    public static String getIntegrityHash(String filePath) throws IOException, NoSuchAlgorithmException {
        MessageDigest md = MessageDigest.getInstance("SHA-256"); // You can choose other algorithms as needed
        byte[] buffer = new byte[8192];
        int bytesRead;

        try (BufferedInputStream fis = new BufferedInputStream(new FileInputStream(filePath))) {
            while ((bytesRead = fis.read(buffer)) != -1) {
                md.update(buffer, 0, bytesRead);
            }
        }

        byte[] digest = md.digest();
        return bytesToHex(digest);
    }

    private static String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02x", b));
        }
        return sb.toString();
    }

    public static boolean verifyIntegrity(String filePath, String expectedHash) throws IOException, NoSuchAlgorithmException {
        String actualHash = getIntegrityHash(filePath);
        return actualHash.equals(expectedHash);
    }

    public static void main(String[] args) throws Exception {
        String filePath = "/path/to/your/file";
        String expectedHash = "your_expected_hash_value";

        if (verifyIntegrity(filePath, expectedHash)) {
            System.out.println("File integrity is valid!");
        } else {
            System.out.println("File integrity is compromised!");
        }
    }
}

Ressourcen