Unsachgemäße Beschränkung von Software-Schnittstellen zu Hardware-Funktionen

Beschreibung

Unsachgemäße Beschränkung von Software-Schnittstellen zu Hardware-Funktionen tritt auf, wenn ein Produkt Software-Kontrolle über Gerätefunktionalität wie Strom- und Taktverwaltung erlaubt, ohne den Zugriff ordnungsgemäß einzuschränken. Dies kann Angreifern ermöglichen, Hardware-Speicher/Register zu modifizieren oder physische Seitenkanale auszunutzen, ohne physischen Gerätezugriff zu benötigen. Moderne Chipsätze enthalten software-zugängliche Strom- und Frequenzskalierung für mobile Geräte, aber diese Funktionen schaffen Sicherheitsrisiken einschließlich Fault-Injection-Angriffen und Seitenkanal-Analyse unter Verwendung eingebauter Strommessung.

Risiko

Uneingeschränkte Hardware-Schnittstellen haben schwerwiegende Sicherheitsauswirkungen. Spannungsmanipulation ermöglicht Fault Injection (Plundervolt). Strommessung ermöglicht Seitenkanal-Angriffe (PLATYPUS). Rowhammer-Angriffe verursachen Speicher-Bit-Flips. CPU-Frequenzmanipulation stört Timing. Thermische Kontrollen können Instabilität verursachen. Debug-Schnittstellen können zugänglich sein. Sicherheitsenklaven können kompromittiert werden. Privilege Escalation wird durch Hardware-Manipulation möglich.

Lösung

Stellen Sie sicher, dass geeignete Zugriffskontrollmechanismen software-steuerbare Funktionen schützen, die physische Betriebsbedingungen wie Taktfrequenz und Spannung ändern. Beschränken Sie den Zugriff auf DVFS-Schnittstellen. Begrenzen Sie die Genauigkeit der Strommessung. Implementieren Sie Kontrollen für Speicher-Refresh-Raten. Erfordern Sie Privilegien für Hardware-Kontrollschnittstellen. Überwachen Sie auf abnormale Hardware-Manipulation. Implementieren Sie Ratenbegrenzung für Hardware-Kontrolloperationen. Verwenden Sie Hardware-Sicherheitsmodule für sensible Operationen.

Häufige Auswirkungen

AuswirkungDetails
IntegritätUmfang: Integrität

Speicher modifizieren; Anwendungsdaten modifizieren - Hardware-Manipulation kann Speicherbeschädigung durch Techniken wie Rowhammer verursachen.
IntegritätUmfang: Integrität

Schutzmechanismus umgehen - Fault Injection kann Sicherheitsprüfungen einschließlich kryptografischer Operationen umgehen.
VertraulichkeitUmfang: Vertraulichkeit

Speicher lesen - Power-Seitenkanal-Angriffe können kryptografische Schlüssel und sensible Daten extrahieren.

Beispielcode und Lösung

Verwundbarer Code

// VERWUNDBAR: Uneingeschränkter Zugriff auf Spannungssteuerung

#include <stdint.h>

// Plundervolt-artiger Angriffsvektor
#define MSR_VOLTAGE_CONTROL 0x150

void vulnerable_voltage_interface(void) {
    // VERWUNDBAR: Jeder Prozess kann Spannungs-MSR lesen/schreiben
    // Keine Berechtigungsprüfung oder Zugriffsbeschränkung

    uint64_t voltage = rdmsr(MSR_VOLTAGE_CONTROL);

    // Angreifer kann unterspannen, um Fehler zu verursachen
    wrmsr(MSR_VOLTAGE_CONTROL, voltage - 0x100);

    // Sicherheitskritische Operation während Unterspannung ausführen
    // Fehler kann falsche Berechnung/Umgehung verursachen
}

// VERWUNDBAR: Uneingeschränkter RAPL- (Strommessungs-) Zugriff
#define MSR_RAPL_POWER_UNIT 0x606
#define MSR_PKG_ENERGY_STATUS 0x611

void vulnerable_rapl_access(void) {
    // VERWUNDBAR: Hochpräzise Stromablesungen verfügbar
    // Können für Power-Seitenkanal-Angriffe verwendet werden (PLATYPUS)

    uint64_t energy_before = rdmsr(MSR_PKG_ENERGY_STATUS);

    // Zieloperation (z.B. AES-Verschlüsselung)
    perform_crypto_operation();

    uint64_t energy_after = rdmsr(MSR_PKG_ENERGY_STATUS);

    // VERWUNDBAR: Energiedifferenz offenbart Operationsdetails
    uint64_t energy_consumed = energy_after - energy_before;
    // Angreifer korreliert Strom mit Schlüssel-Bits
}

// VERWUNDBAR: Uneingeschränkter Cache-Flush
void vulnerable_cache_control(void) {
    // VERWUNDBAR: CLFLUSH verfügbar für unprivilegierten Code
    // Ermöglicht Rowhammer-Angriffe und Cache-Timing-Angriffe

    volatile char* target = (volatile char*)0x12340000;

    while (1) {
        // Wiederholt leeren und zugreifen, um Bit-Flips zu verursachen
        _mm_clflush((void*)target);
        *target;
        _mm_clflush((void*)(target + 4096));
        *(target + 4096);
        // VERWUNDBAR: Kann DRAM-Bit-Flips verursachen (Rowhammer)
    }
}

// VERWUNDBAR: Uneingeschränkte Frequenzskalierung
void vulnerable_frequency_control(void) {
    // VERWUNDBAR: Software kann CPU-Frequenz ändern
    // Kann für Timing-Angriffe oder Fault Injection verwendet werden

    // Maximale Frequenz anfordern
    write_freq_request(MAX_FREQ);

    // Oder Minimum anfordern, um Sicherheitsprüfungen zu verlangsamen
    write_freq_request(MIN_FREQ);

    // Schnelles Umschalten kann Instabilität verursachen
}
// VERWUNDBAR: Hardware mit uneingeschränkten Kontrollschnittstellen

module vulnerable_power_controller (
    input wire clk,
    input wire reset_n,
    // VERWUNDBAR: Keine Berechtigungsprüfung
    input wire [7:0] voltage_request,
    input wire [7:0] frequency_request,
    input wire control_valid,
    output reg [7:0] voltage_setting,
    output reg [7:0] frequency_setting
);

    // VERWUNDBAR: Direkte Kontrolle ohne Einschränkungen
    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            voltage_setting <= 8'd128;    // Nennspannung
            frequency_setting <= 8'd128;  // Nennfrequenz
        end
        else if (control_valid) begin
            // VERWUNDBAR: Jede Spannung/Frequenz ohne Prüfung akzeptieren
            // - Keine Mindest-/Höchstgrenzen
            // - Keine Berechtigungsüberprüfung
            // - Keine Ratenbegrenzung
            voltage_setting <= voltage_request;
            frequency_setting <= frequency_request;
        end
    end

    // Keine Überwachung auf Fault-Injection-Muster
    // Kein Schutz gegen schnelle Änderungen

endmodule

// VERWUNDBAR: Uneingeschränkte Strommessung
module vulnerable_power_meter (
    input wire clk,
    input wire reset_n,
    input wire [15:0] power_sense,
    input wire read_request,
    output reg [31:0] energy_counter,
    output reg [15:0] power_reading
);

    // VERWUNDBAR: Hochauflösende Stromablesungen zugänglich
    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            energy_counter <= 32'h0;
            power_reading <= 16'h0;
        end
        else begin
            // Hochauflösende Energie akkumulieren
            energy_counter <= energy_counter + power_sense;

            // VERWUNDBAR: Präzise Stromablesung zurückgeben
            if (read_request) begin
                power_reading <= power_sense;
            end
        end
    end

    // Keine Zugriffskontrolle
    // Keine Auflösungsbegrenzung
    // Ermöglicht Power-Seitenkanal-Angriffe

endmodule

Sichere Lösung

// SICHER: Eingeschränkter Zugriff auf Hardware-Kontrollschnittstellen

#include <stdint.h>

// SICHER: Spannungssteuerung mit Einschränkungen
int secure_voltage_interface(uint64_t new_voltage, int privilege_level) {
    // SICHER: Erhöhte Privilegien erforderlich
    if (privilege_level < PRIVILEGE_KERNEL) {
        return -EPERM;
    }

    // SICHER: Spannungsbereich validieren
    if (new_voltage < VOLTAGE_MIN || new_voltage > VOLTAGE_MAX) {
        return -EINVAL;
    }

    // SICHER: Ratenbegrenzung
    static uint64_t last_change_time = 0;
    uint64_t current_time = get_current_time();

    if (current_time - last_change_time < VOLTAGE_CHANGE_COOLDOWN) {
        return -EAGAIN;
    }

    // SICHER: Spannungsänderung protokollieren
    audit_log("Spannungsänderung: %llx durch Privileg %d", new_voltage, privilege_level);

    // Kontrollierte Spannungsänderung durchführen
    wrmsr(MSR_VOLTAGE_CONTROL, new_voltage);
    last_change_time = current_time;

    return 0;
}

// SICHER: Eingeschränkter RAPL-Zugriff
int secure_rapl_access(uint64_t* energy, int privilege_level) {
    // SICHER: Erhöhte Privilegien für präzise Ablesungen erforderlich
    if (privilege_level < PRIVILEGE_ADMIN) {
        return -EPERM;
    }

    uint64_t raw_energy = rdmsr(MSR_PKG_ENERGY_STATUS);

    // SICHER: Auflösung reduzieren, um Seitenkanal-Angriffe zu verhindern
    // Auf nächstes 1mJ runden statt Mikrojoule-Präzision
    *energy = (raw_energy / 1000) * 1000;

    // SICHER: Rauschen zu Ablesungen hinzufügen
    *energy += get_random() % 1000;

    return 0;
}

// SICHER: Eingeschränkte Cache-Kontrolle
int secure_cache_flush(void* addr, size_t size, int privilege_level) {
    // SICHER: Kernel-Privileg für Cache-Flush erforderlich
    if (privilege_level < PRIVILEGE_KERNEL) {
        return -EPERM;
    }

    // SICHER: Adressbereich validieren
    if (!is_valid_kernel_address(addr, size)) {
        return -EFAULT;
    }

    // SICHER: Ratenbegrenzung zur Verhinderung von Rowhammer
    static int flush_count = 0;
    static uint64_t window_start = 0;
    uint64_t current_time = get_current_time();

    if (current_time - window_start > RATE_LIMIT_WINDOW) {
        flush_count = 0;
        window_start = current_time;
    }

    if (++flush_count > MAX_FLUSHES_PER_WINDOW) {
        audit_log("Cache-Flush-Ratenlimit überschritten");
        return -EBUSY;
    }

    // Cache-Flush durchführen
    for (size_t i = 0; i < size; i += CACHE_LINE_SIZE) {
        _mm_clflush((char*)addr + i);
    }

    return 0;
}

// SICHER: Sichere Frequenzsteuerung
int secure_frequency_control(uint64_t requested_freq, int privilege_level) {
    // SICHER: Erhöhte Privilegien erforderlich
    if (privilege_level < PRIVILEGE_ADMIN) {
        return -EPERM;
    }

    // SICHER: Frequenzbereich validieren
    if (requested_freq < FREQ_MIN || requested_freq > FREQ_MAX) {
        return -EINVAL;
    }

    // SICHER: Nur schrittweise Frequenzänderungen
    uint64_t current_freq = read_current_frequency();
    uint64_t max_step = FREQ_MAX_STEP;

    if (abs(requested_freq - current_freq) > max_step) {
        // Schrittweise ändern, um Fault Injection zu verhindern
        requested_freq = current_freq +
            (requested_freq > current_freq ? max_step : -max_step);
    }

    write_freq_request(requested_freq);

    return 0;
}
// SICHER: Hardware mit sicheren Kontrollschnittstellen

module secure_power_controller (
    input wire clk,
    input wire reset_n,
    input wire [1:0] privilege_level,  // 0=Benutzer, 1=Kernel, 2=Sicher
    input wire [7:0] voltage_request,
    input wire [7:0] frequency_request,
    input wire control_valid,
    output reg [7:0] voltage_setting,
    output reg [7:0] frequency_setting,
    output reg access_denied,
    output reg rate_limit_exceeded
);

    // SICHER: Erforderliche Berechtigungsstufe für Hardware-Kontrolle
    parameter REQUIRED_PRIVILEGE = 2'd2;  // Nur sicherer Modus

    // SICHER: Gültige Spannungs-/Frequenzbereiche
    parameter VOLTAGE_MIN = 8'd96;   // ~75% Nennwert
    parameter VOLTAGE_MAX = 8'd160;  // ~125% Nennwert
    parameter FREQ_MIN = 8'd32;
    parameter FREQ_MAX = 8'd224;

    // SICHER: Ratenbegrenzung
    reg [15:0] change_cooldown;
    parameter COOLDOWN_CYCLES = 16'd10000;

    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            voltage_setting <= 8'd128;
            frequency_setting <= 8'd128;
            access_denied <= 1'b0;
            rate_limit_exceeded <= 1'b0;
            change_cooldown <= 16'h0;
        end
        else begin
            // Abkühlung dekrementieren
            if (change_cooldown > 0) begin
                change_cooldown <= change_cooldown - 1;
            end

            access_denied <= 1'b0;
            rate_limit_exceeded <= 1'b0;

            if (control_valid) begin
                // SICHER: Berechtigungsstufe prüfen
                if (privilege_level < REQUIRED_PRIVILEGE) begin
                    access_denied <= 1'b1;
                end
                // SICHER: Ratenlimit prüfen
                else if (change_cooldown > 0) begin
                    rate_limit_exceeded <= 1'b1;
                end
                // SICHER: Spannungsbereich validieren
                else if (voltage_request < VOLTAGE_MIN ||
                         voltage_request > VOLTAGE_MAX) begin
                    access_denied <= 1'b1;
                end
                // SICHER: Frequenzbereich validieren
                else if (frequency_request < FREQ_MIN ||
                         frequency_request > FREQ_MAX) begin
                    access_denied <= 1'b1;
                end
                else begin
                    // SICHER: Kontrollierte Änderung anwenden
                    voltage_setting <= voltage_request;
                    frequency_setting <= frequency_request;
                    change_cooldown <= COOLDOWN_CYCLES;
                end
            end
        end
    end

endmodule

// SICHER: Sichere Strommessung mit reduzierter Präzision
module secure_power_meter (
    input wire clk,
    input wire reset_n,
    input wire [15:0] power_sense,
    input wire read_request,
    input wire [1:0] privilege_level,
    input wire [7:0] random_noise,  // Externer TRNG
    output reg [31:0] energy_counter,
    output reg [15:0] power_reading,
    output reg access_denied
);

    parameter REQUIRED_PRIVILEGE = 2'd1;  // Kernel erforderlich

    // Interner hochauflösender Zähler
    reg [47:0] internal_energy;

    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            internal_energy <= 48'h0;
            energy_counter <= 32'h0;
            power_reading <= 16'h0;
            access_denied <= 1'b0;
        end
        else begin
            // Immer akkumulieren (intern)
            internal_energy <= internal_energy + power_sense;

            access_denied <= 1'b0;

            if (read_request) begin
                // SICHER: Berechtigung prüfen
                if (privilege_level < REQUIRED_PRIVILEGE) begin
                    access_denied <= 1'b1;
                    power_reading <= 16'h0;
                    energy_counter <= 32'h0;
                end
                else begin
                    // SICHER: Präzision reduzieren (obere 32 von 48 Bits)
                    // SICHER: Rauschen hinzufügen, um Seitenkanal zu verhindern
                    energy_counter <= internal_energy[47:16] +
                                     {24'h0, random_noise};

                    // SICHER: Nur grobe Stromablesung
                    power_reading <= {power_sense[15:8], 8'h00} +
                                    {8'h0, random_noise};
                end
            end
        end
    end

endmodule

CVE-Beispiele

  • CVE-2019-11157 (Plundervolt): Intel-Prozessor-Spannungseinstellungs-Schwachstelle ermöglicht Privilege Escalation und Sicherheitsenklaven-Umgehung
  • CVE-2020-8694/8695 (PLATYPUS): RAPL-Schnittstellen-Zugriffskontrollprobleme ermöglichen Power-Seitenkanal-Angriffe
  • CVE-2015-0565: NaCl erlaubte CLFLUSH-Instruktion und ermöglichte Rowhammer-Angriffe

Verwandte CWEs

  • CWE-285: Unsachgemäße Autorisierung (übergeordnet)
  • CWE-1300: Unsachgemäßer Schutz physischer Seitenkanale (verwandt)
  • CWE-1247: Unsachgemäßer Schutz gegen Spannungs- und Taktglitches (verwandt)
  • CAPEC-624: Hardware Fault Injection (Angriffsmuster)
  • CAPEC-625: Mobile Device Fault Injection (Angriffsmuster)

Referenzen

  1. MITRE Corporation. "CWE-1256: Improper Restriction of Software Interfaces to Hardware Features." https://cwe.mitre.org/data/definitions/1256.html
  2. Plundervolt: Software-based Fault Injection Attacks against Intel SGX
  3. PLATYPUS: Software-based Power Side-Channel Attacks on x86
  4. Rowhammer: Flipping Bits in Memory Without Accessing Them