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
| Auswirkung | Details |
|---|---|
| Vertraulichkeit | Bereich: Vertraulichkeit Anwendungsdaten lesen - Angreifer können sensible Informationen lesen, indem sie auf den uneingeschränkten Speichermechanismus zugreifen. |
| Integrität | Bereich: 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
- MITRE Corporation. "CWE-921: Storage of Sensitive Data in a Mechanism without Access Control." https://cwe.mitre.org/data/definitions/921.html
- OWASP. "Insecure Data Storage." https://owasp.org/www-project-mobile-top-10/
- Android Developers. "Data and file storage overview." https://developer.android.com/training/data-storage