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

AuswirkungDetails
VertraulichkeitBereich: Datenexposition

Unverschlüsselte Daten können von jedem mit Zugriff auf Speicher oder Netzwerkverkehr gelesen werden.
ComplianceBereich: Regulatorische Verstöße

Die unverschlüsselte Speicherung von PII, Finanz- oder Gesundheitsdaten verletzt DSGVO, PCI-DSS, HIPAA.
IntegritätBereich: 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


Referenzen

  1. MITRE. "CWE-311: Missing Encryption of Sensitive Data." https://cwe.mitre.org/data/definitions/311.html

  2. OWASP. "Cryptographic Storage Cheat Sheet." https://cheatsheetseries.owasp.org/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html