Fehlende Verschlüsselung sensibler Daten
Beschreibung
Fehlende Verschlüsselung sensibler Daten tritt auf, wenn Software sensible oder kritische Informationen vor der Speicherung oder Übertragung nicht verschlüsselt. Dies exponiert Daten gegenüber unbefugten Parteien, die Netzwerkverkehr abfangen, auf Speichermedien zugreifen oder andere Schwachstellen ausnutzen können. Sensible Daten umfassen Passwörter, Finanzinformationen, persönliche Gesundheitsinformationen, Session-Token und private Schlüssel. Ohne Verschlüsselung sind diese Daten für jeden lesbar, der Zugriff darauf erlangt.
Risiko
Unverschlüsselte sensible Daten sind eine kritische Schwachstelle. Datenlecks, die unverschlüsselte Datenbanken exponieren, haben Milliarden von Benutzern betroffen. Netzwerkabfangen (Man-in-the-Middle-Angriffe) kann unverschlüsselte Anmeldedaten während der Übertragung erfassen. Physischer Zugriff auf Speichermedien exponiert unverschlüsselte ruhende Daten. Compliance-Frameworks (PCI-DSS, HIPAA, DSGVO) erfordern die Verschlüsselung sensibler Daten, und Verstöße führen zu erheblichen Bußgeldern.
Lösung
Verschlüsseln Sie alle sensiblen ruhenden Daten mit AES-256 oder ähnlich starken Algorithmen. Verwenden Sie TLS 1.3 für Daten während der Übertragung. Implementieren Sie ordnungsgemäßes Schlüsselmanagement - kodieren Sie niemals Schlüssel hart ein. Verwenden Sie dedizierte Verschlüsselungsbibliotheken, keine benutzerdefinierten Implementierungen. Verschlüsseln Sie Datenbankspalten, die PII oder Anmeldedaten enthalten. Verwenden Sie Vollverschlüsselung für Speichermedien. Implementieren Sie Envelope-Verschlüsselung für Cloud-Umgebungen. Erwägen Sie Datenklassifizierung, um zu identifizieren, was Verschlüsselung benötigt.
Häufige Auswirkungen
| Auswirkung | Details |
|---|---|
| Vertraulichkeit | Bereich: Datenexposition Unverschlüsselte Daten können von jedem mit Zugriff auf Speicher oder Netzwerkverkehr gelesen werden. |
| Compliance | Bereich: Regulatorische Verstöße Die unverschlüsselte Speicherung von PII, Finanz- oder Gesundheitsdaten verletzt DSGVO, PCI-DSS, HIPAA. |
| Integrität | Bereich: Datenmanipulation Unverschlüsselte Daten können ohne Erkennung modifiziert werden. |
Beispielcode + Korrigierter Code
Anfälliger Code
# ANFÄLLIG: Passwörter im Klartext gespeichert
class User(db.Model):
username = db.Column(db.String(80))
password = db.Column(db.String(120)) # Klartext!
def create_user(username, password):
user = User(username=username, password=password)
db.session.add(user)
db.session.commit()
# ANFÄLLIG: Sensible Daten in Klartextdatei
def save_api_keys(keys):
with open('api_keys.txt', 'w') as f:
for key in keys:
f.write(f"{key}\n") # Klartext!
# ANFÄLLIG: HTTP statt HTTPS
import requests
def send_credentials(username, password):
# Sendet über unverschlüsseltes HTTP!
requests.post('http://api.example.com/login', json={
'username': username,
'password': password
})
# ANFÄLLIG: Unverschlüsselte Datenbankverbindung
def connect_database():
return psycopg2.connect(
host='db.example.com',
database='production',
user='app',
password='secret'
# Kein SSL/TLS!
)
// ANFÄLLIG: Klartext-Speicherung sensibler Daten
public class UserService {
public void saveUser(User user) {
// Passwort als Klartext gespeichert
String sql = "INSERT INTO users (username, password, ssn) VALUES (?, ?, ?)";
jdbcTemplate.update(sql,
user.getUsername(),
user.getPassword(), // Klartext!
user.getSsn() // PII unverschlüsselt!
);
}
}
// ANFÄLLIG: Unverschlüsselte Dateispeicherung
public class DataExporter {
public void exportUserData(List<User> users) throws IOException {
try (FileWriter writer = new FileWriter("users.csv")) {
for (User user : users) {
// PII im Klartext geschrieben
writer.write(user.getName() + "," +
user.getSsn() + "," +
user.getCreditCard() + "\n");
}
}
}
}
// ANFÄLLIG: Unverschlüsselte Konfiguration
@Configuration
public class AppConfig {
// Sensible Daten in Klartext-Konfiguration
@Value("${db.password}") // Aus Klartext application.properties
private String dbPassword;
}
// ANFÄLLIG: Klartextdaten in localStorage
function saveUserData(user) {
// Sensible Daten unverschlüsselt im Browser gespeichert
localStorage.setItem('user_session', JSON.stringify({
userId: user.id,
token: user.token,
creditCard: user.creditCard // Klartext!
}));
}
// ANFÄLLIG: Unverschlüsselte API-Kommunikation
async function submitPayment(cardNumber, cvv, amount) {
// Zahlungsdaten über HTTP senden
const response = await fetch('http://api.example.com/payment', {
method: 'POST',
body: JSON.stringify({ cardNumber, cvv, amount })
});
return response.json();
}
Korrigierter Code
# SICHER: Ordnungsgemäß gehashte Passwörter und verschlüsselte Daten
from argon2 import PasswordHasher
from cryptography.fernet import Fernet
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
import os
import base64
ph = PasswordHasher()
class User(db.Model):
username = db.Column(db.String(80))
password_hash = db.Column(db.String(256)) # Gehasht!
def create_user(username, password):
# Passwort mit Argon2 hashen
password_hash = ph.hash(password)
user = User(username=username, password_hash=password_hash)
db.session.add(user)
db.session.commit()
def verify_password(stored_hash, password):
try:
ph.verify(stored_hash, password)
return True
except:
return False
# SICHER: Verschlüsselte Dateispeicherung
def get_encryption_key():
# Schlüssel aus Umgebung oder Schlüsselmanagementsystem
key = os.environ.get('ENCRYPTION_KEY')
return base64.urlsafe_b64decode(key)
def save_api_keys_encrypted(keys):
fernet = Fernet(get_encryption_key())
encrypted_data = []
for key in keys:
encrypted_data.append(fernet.encrypt(key.encode()))
with open('api_keys.enc', 'wb') as f:
for encrypted_key in encrypted_data:
f.write(encrypted_key + b'\n')
def load_api_keys_encrypted():
fernet = Fernet(get_encryption_key())
with open('api_keys.enc', 'rb') as f:
encrypted_keys = f.read().strip().split(b'\n')
return [fernet.decrypt(key).decode() for key in encrypted_keys]
# SICHER: Nur HTTPS
import requests
def send_credentials_secure(username, password):
# Verwendung von HTTPS
response = requests.post('https://api.example.com/login',
json={'username': username, 'password': password},
verify=True # SSL-Zertifikat verifizieren
)
return response
# SICHER: Verschlüsselte Datenbankverbindung
def connect_database_secure():
return psycopg2.connect(
host='db.example.com',
database='production',
user='app',
password=os.environ['DB_PASSWORD'],
sslmode='verify-full', # SSL erforderlich
sslrootcert='/path/to/ca-cert.pem'
)
// SICHER: Verschlüsselte sensible Daten
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec;
import org.springframework.security.crypto.argon2.Argon2PasswordEncoder;
@Service
public class SecureUserService {
private final Argon2PasswordEncoder passwordEncoder = new Argon2PasswordEncoder();
private final EncryptionService encryptionService;
public void saveUser(User user) {
// Passwort hashen
String passwordHash = passwordEncoder.encode(user.getPassword());
// PII verschlüsseln
String encryptedSsn = encryptionService.encrypt(user.getSsn());
String sql = "INSERT INTO users (username, password_hash, ssn_encrypted) VALUES (?, ?, ?)";
jdbcTemplate.update(sql, user.getUsername(), passwordHash, encryptedSsn);
}
}
@Service
public class EncryptionService {
private SecretKey key; // Aus sicherem Schlüsselmanagement geladen
public String encrypt(String plaintext) throws Exception {
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
byte[] iv = generateSecureIV();
GCMParameterSpec parameterSpec = new GCMParameterSpec(128, iv);
cipher.init(Cipher.ENCRYPT_MODE, key, parameterSpec);
byte[] ciphertext = cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8));
// IV dem Chiffretext voranstellen
byte[] combined = new byte[iv.length + ciphertext.length];
System.arraycopy(iv, 0, combined, 0, iv.length);
System.arraycopy(ciphertext, 0, combined, iv.length, ciphertext.length);
return Base64.getEncoder().encodeToString(combined);
}
public String decrypt(String encryptedData) throws Exception {
byte[] combined = Base64.getDecoder().decode(encryptedData);
byte[] iv = Arrays.copyOfRange(combined, 0, 12);
byte[] ciphertext = Arrays.copyOfRange(combined, 12, combined.length);
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
GCMParameterSpec parameterSpec = new GCMParameterSpec(128, iv);
cipher.init(Cipher.DECRYPT_MODE, key, parameterSpec);
return new String(cipher.doFinal(ciphertext), StandardCharsets.UTF_8);
}
}
// SICHER: Verschlüsselte Konfiguration
@Configuration
public class SecureAppConfig {
// Verwendung verschlüsselter Properties oder Secrets Manager
@Value("${db.password}") // Jasypt-verschlüsselt oder aus Vault
private String dbPassword;
// Oder AWS Secrets Manager verwenden
@Bean
public String getDbPassword() {
return secretsManager.getSecretValue("db-password");
}
}
// SICHER: Verschlüsselter Browser-Speicher
const crypto = require('crypto-js');
function saveUserDataEncrypted(user, encryptionKey) {
// Nur wesentliche nicht-sensible Daten speichern
const sessionData = {
userId: user.id,
token: user.token
// Kreditkarte NICHT speichern!
};
// Vor Speicherung verschlüsseln
const encrypted = crypto.AES.encrypt(
JSON.stringify(sessionData),
encryptionKey
).toString();
sessionStorage.setItem('user_session', encrypted); // sessionStorage verwenden, nicht localStorage
}
function loadUserDataEncrypted(encryptionKey) {
const encrypted = sessionStorage.getItem('user_session');
if (!encrypted) return null;
const decrypted = crypto.AES.decrypt(encrypted, encryptionKey);
return JSON.parse(decrypted.toString(crypto.enc.Utf8));
}
// SICHER: Nur HTTPS für sensible Daten
async function submitPaymentSecure(cardNumber, cvv, amount) {
// Tokenisieren statt rohe Kartendaten zu senden
const token = await tokenizeCard(cardNumber, cvv);
// Nur HTTPS
const response = await fetch('https://api.example.com/payment', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Strict-Transport-Security': 'max-age=31536000'
},
body: JSON.stringify({ paymentToken: token, amount })
});
return response.json();
}
Ausgenutzt in der Praxis
Equifax-Datenleck (2017)
Das Equifax-Leck exponierte 147 Millionen Datensätze. Obwohl der initiale Vektor eine Web-Schwachstelle war, wurde der Schäden durch sensible Daten ohne angemessene Verschlüsselung verschlimmert, einschließlich SSNs im Klartext.
Adobe-Passwortleck (2013)
Adobe erlitt ein Leck, das 153 Millionen Benutzeraufzeichnungen exponierte. Passwörter wurden mit 3DES-ECB verschlüsselt (nicht gehasht), was Angreifern ermöglichte, Millionen von Passwörtern durch Musteranalyse zu knacken.
Marriott-Datenleck (2018)
Das Leck des Marriott Starwood-Reservierungssystems exponierte 383 Millionen Gästeaufzeichnungen, einschließlich unverschlüsselter Passnummern für 5,25 Millionen Gäste.
Tools zum Testen/Ausnutzen
-
Wireshark — Netzwerkverkehr auf unverschlüsselte Daten analysieren.
-
Burp Suite — HTTP-Verkehr abfangen und analysieren.
-
SQLite Browser — Unverschlüsselte lokale Datenbanken untersuchen.
-
testssl.sh — TLS-Konfiguration testen.
CVE-Beispiele
-
CVE-2019-1010238 — GNOME Gnome-keyring schwache Verschlüsselung.
-
CVE-2021-22893 — Pulse Secure Exposition sensibler Daten.
-
CVE-2020-8945 — GPG sensible Daten im Klartext.
Referenzen
-
MITRE. "CWE-311: Missing Encryption of Sensitive Data." https://cwe.mitre.org/data/definitions/311.html
-
OWASP. "Cryptographic Storage Cheat Sheet." https://cheatsheetseries.owasp.org/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html