Speicherung sensibler Daten in einem Mechanismus ohne Zugriffskontrolle

Beschreibung

Speicherung sensibler Daten in einem Mechanismus ohne Zugriffskontrolle tritt auf, wenn Software sensible Informationen in einem Dateisystem oder Gerät speichert, das keine eingebauten Zugriffskontrollmechanismen hat. Speichermedien wie Speicherkarten, Disketten, CDs, USB-Laufwerke und externer Speicher haben typischerweise keine Zugriffsbeschränkungen. Auf mobilen Plattformen wie Android ist externer Speicher (SD-Karten) global lesbar und beschreibbar durch andere Anwendungen und kann über USB-Verbindungen oder durch physisches Entfernen des Speichermediums zugegriffen werden. Wenn sensible Daten an diesen ungeschützten Orten gespeichert werden, kann jede Anwendung oder jeder Benutzer mit physischem Zugriff die Daten lesen, ändern oder löschen.

Risiko

Das Speichern sensibler Daten ohne Zugriffskontrollen setzt sie unbefugtem Zugriff aus mehreren Vektoren aus. Auf mobilen Geräten kann jede installierte Anwendung extern gespeicherte Daten lesen. Physischer Zugriff auf das Gerät oder Speichermedium ermöglicht Datenextraktion. USB-Debugging oder Massenspeichermodus ermöglicht Computerzugriff auf die Daten. Angreifer können gespeicherte Daten modifizieren, um das Anwendungsverhalten zu manipulieren oder bösartige Inhalte einzuschleusen. Gelöschte Daten können von unverschlüsselten Speichermedien wiederherstellbar sein. Diese Schwachstelle ist besonders gefährlich für Anwendungen, die Anmeldedaten, persönliche Informationen, Finanzdaten oder Gesundheitsdaten verarbeiten.

Lösung

Speichern Sie sensible Daten nur an Orten mit eingebauten Zugriffskontrollen. Auf Android verwenden Sie internen Speicher (privates Verzeichnis der App) anstelle von externem Speicher. Verschlüsseln Sie sensible Daten, bevor Sie sie irgendwo speichern. Verwenden Sie plattformbereitgestellte sichere Speichermechanismen (Keychain auf iOS, Android Keystore). Implementieren Sie Verschlüsselung auf Dateiebene mit Schlüsseln pro Datei. Überprüfen Sie die Berechtigungen des Speicherorts, bevor Sie sensible Daten schreiben. Berücksichtigen Sie Datensensibilitätsklassifizierungen und Speicherrichtlinien. Für Daten, die extern gespeichert werden müssen, verwenden Sie starke Verschlüsselung mit ordnungsgemäß verwalteten Schlüsseln. Speichern Sie niemals Anmeldedaten, Tokens oder persönlich identifizierbare Informationen an weltweit lesbaren Orten.

Häufige Auswirkungen

AuswirkungDetails
VertraulichkeitBereich: Vertraulichkeit

Anwendungsdaten lesen - Angreifer können sensible Informationen lesen, indem sie auf den uneingeschränkten Speichermechanismus zugreifen.
IntegritätBereich: Integrität

Anwendungsdaten modifizieren - Angreifer können sensible Informationen ändern oder löschen, indem sie auf den uneingeschränkten Speichermechanismus zugreifen.

Beispielcode

Anfälliger Code

// Anfällig: Android-App speichert Daten auf externem Speicher
public class VulnerableDataStorage {

    public void saveSensitiveData(String data) {
        // Anfällig: Externer Speicher ist weltweit lesbar
        File externalDir = Environment.getExternalStorageDirectory();
        File dataFile = new File(externalDir, "myapp/credentials.txt");

        try (FileWriter writer = new FileWriter(dataFile)) {
            writer.write(data);  // Jede App kann das lesen!
        } catch (IOException e) {
            Log.e(TAG, "Fehler beim Speichern der Daten", e);
        }
    }

    public void saveApiKey(String apiKey) {
        // Anfällig: SharedPreferences auf externem Speicher
        SharedPreferences prefs = getSharedPreferences(
            Environment.getExternalStorageDirectory() + "/myapp/config",
            Context.MODE_WORLD_READABLE  // Veraltet und gefährlich!
        );
        prefs.edit().putString("api_key", apiKey).apply();
    }
}
// Anfällig: iOS-App speichert Daten an ungeschütztem Ort
class VulnerableDataManager {

    func saveCredentials(username: String, password: String) {
        // Anfällig: Speicherung im Documents-Verzeichnis ohne Schutz
        let documentsPath = FileManager.default.urls(
            for: .documentDirectory,
            in: .userDomainMask
        ).first!

        let credentialsFile = documentsPath.appendingPathComponent("credentials.json")

        let credentials = ["username": username, "password": password]
        let data = try? JSONEncoder().encode(credentials)

        // Anfällig: Keine Verschlüsselung, keine Datenschutzklasse
        try? data?.write(to: credentialsFile)
    }
}
# Anfällig: Desktop-App speichert Daten im Temp-Verzeichnis
import tempfile
import json

class VulnerableConfig:

    def save_config(self, api_key, database_password):
        # Anfällig: Temp-Verzeichnis ist auf vielen Systemen weltweit lesbar
        config_path = tempfile.gettempdir() + '/myapp_config.json'

        config = {
            'api_key': api_key,
            'db_password': database_password
        }

        with open(config_path, 'w') as f:
            json.dump(config, f)

        # Jeder Benutzer auf dem System kann diese Datei lesen

Korrigierter Code

// Korrigiert: Android-App verwendet sicheren internen Speicher
public class FixedDataStorage {

    private Context context;

    public FixedDataStorage(Context context) {
        this.context = context;
    }

    public void saveSensitiveData(String data) {
        // Korrigiert: Internen Speicher verwenden - nur diese App kann zugreifen
        File internalDir = context.getFilesDir();
        File dataFile = new File(internalDir, "credentials.enc");

        try {
            // Korrigiert: Vor dem Speichern verschlüsseln
            byte[] encryptedData = encrypt(data.getBytes());

            try (FileOutputStream fos = new FileOutputStream(dataFile)) {
                fos.write(encryptedData);
            }
        } catch (Exception e) {
            Log.e(TAG, "Fehler beim Speichern der Daten", e);
        }
    }

    public void saveApiKey(String apiKey) {
        // Korrigiert: EncryptedSharedPreferences verwenden
        try {
            MasterKey masterKey = new MasterKey.Builder(context)
                .setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
                .build();

            SharedPreferences sharedPreferences = EncryptedSharedPreferences.create(
                context,
                "secure_prefs",
                masterKey,
                EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
                EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
            );

            sharedPreferences.edit().putString("api_key", apiKey).apply();
        } catch (Exception e) {
            Log.e(TAG, "Fehler beim Speichern des API-Schlüssels", e);
        }
    }

    // Korrigiert: Android Keystore für kryptographische Schlüssel verwenden
    public void saveSecretKey(String keyAlias, SecretKey key) {
        try {
            KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
            keyStore.load(null);
            keyStore.setEntry(keyAlias,
                new KeyStore.SecretKeyEntry(key),
                new KeyProtection.Builder(KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
                    .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
                    .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
                    .build()
            );
        } catch (Exception e) {
            Log.e(TAG, "Fehler beim Speichern des Schlüssels", e);
        }
    }
}
// Korrigiert: iOS-App verwendet Keychain für sensible Daten
import Security

class FixedDataManager {

    func saveCredentials(username: String, password: String) {
        // Korrigiert: Passwort in Keychain speichern
        let passwordData = password.data(using: .utf8)!

        let query: [String: Any] = [
            kSecClass as String: kSecClassGenericPassword,
            kSecAttrAccount as String: username,
            kSecAttrService as String: "com.myapp.credentials",
            kSecValueData as String: passwordData,
            // Korrigiert: Gerätentsperrung für Zugriff erforderlich
            kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlockedThisDeviceOnly
        ]

        // Vorhandenen Eintrag löschen
        SecItemDelete(query as CFDictionary)

        // Neuen Eintrag hinzufügen
        let status = SecItemAdd(query as CFDictionary, nil)
        if status != errSecSuccess {
            print("Fehler beim Speichern in Keychain: \(status)")
        }
    }

    func saveToProtectedFile(data: Data, filename: String) {
        let documentsPath = FileManager.default.urls(
            for: .documentDirectory,
            in: .userDomainMask
        ).first!

        let fileURL = documentsPath.appendingPathComponent(filename)

        do {
            // Korrigiert: Vollständigen Schutz verwenden - verschlüsselt bei gesperrtem Gerät
            try data.write(to: fileURL, options: .completeFileProtection)
        } catch {
            print("Fehler beim Speichern geschützter Datei: \(error)")
        }
    }
}
# Korrigiert: Desktop-App verwendet sicheren Speicher
import os
import json
from cryptography.fernet import Fernet
import keyring

class FixedConfig:

    def __init__(self, app_name: str):
        self.app_name = app_name
        self._init_encryption_key()

    def _init_encryption_key(self):
        # Verschlüsselungsschlüssel in OS-Keyring speichern
        stored_key = keyring.get_password(self.app_name, 'encryption_key')
        if stored_key:
            self.fernet = Fernet(stored_key.encode())
        else:
            key = Fernet.generate_key()
            keyring.set_password(self.app_name, 'encryption_key', key.decode())
            self.fernet = Fernet(key)

    def save_api_key(self, api_key: str):
        # Korrigiert: Sensible Werte im OS-Keyring speichern
        keyring.set_password(self.app_name, 'api_key', api_key)

    def save_database_password(self, password: str):
        # Korrigiert: Im OS-Keyring speichern
        keyring.set_password(self.app_name, 'db_password', password)

    def save_config(self, config: dict):
        # Korrigiert: Privates Verzeichnis des Benutzers verwenden
        config_dir = os.path.join(os.path.expanduser('~'), '.config', self.app_name)
        os.makedirs(config_dir, mode=0o700, exist_ok=True)  # Nur Eigentümer

        config_path = os.path.join(config_dir, 'config.enc')

        # Korrigiert: Sensible Daten verschlüsseln
        config_json = json.dumps(config)
        encrypted = self.fernet.encrypt(config_json.encode())

        with open(config_path, 'wb') as f:
            f.write(encrypted)

        # Korrigiert: Restriktive Berechtigungen setzen
        os.chmod(config_path, 0o600)

Verwandte CWEs

  • CWE-922: Insecure Storage of Sensitive Information (Eltern)
  • CWE-312: Cleartext Storage of Sensitive Information (verwandt)
  • CWE-311: Missing Encryption of Sensitive Data (verwandt)
  • CWE-732: Incorrect Permission Assignment for Critical Resource (verwandt)

Referenzen

  1. MITRE Corporation. "CWE-921: Storage of Sensitive Data in a Mechanism without Access Control." https://cwe.mitre.org/data/definitions/921.html
  2. OWASP. "Insecure Data Storage." https://owasp.org/www-project-mobile-top-10/
  3. Android Developers. "Data and file storage overview." https://developer.android.com/training/data-storage