Sicherheitsversionsnummer auf ältere Versionen änderbar

Beschreibung

Die Sicherheitsversionsnummer auf ältere Versionen änderbar tritt auf, wenn die Sicherheitsversionsnummer in Hardware änderbar ist, was die Möglichkeit ergibt, die Boot-Firmware auf verwundbare Code-Versionen zurückzusetzen (Roll-back). Systems-on-Chip (SoC), die Secure oder Verified Boot implementieren, unterstützen möglicherweise Sicherheitsversionsnummern, um Firmware-Downgrades zu verhindern. Wenn diese Versionsnummern änderbar sind, können Angreifer Roll-back-Angriffe ausführen, um auf ausnutzbare Firmware-Versionen zurückzukehren oder legitime Upgrades durch Denial-of-Service zu blockieren.

Risiko

Änderbare Sicherheitsversionsnummern haben schwerwiegende Auswirkungen. Roll-back auf verwundbare Firmware. Bekannte Exploits werden wieder nutzbar. Downgrade-Angriffe ermöglicht. Sicherheitspatches entwertet. Upgrade-Denial-of-Service. Authentifizierungsumgehung durch ältere Firmware. Integritätskompromittierung. Vertraulichkeitsverletzung durch bekannte Schwachstellen. Hohe Wahrscheinlichkeit wenn Versionsspeicher nicht ordnungsgemäß geschützt ist.

Lösung

Speichern Sie Sicherheitsversionsdaten in schreibgeschützten Registern oder implementieren Sie strikte Zugriffskontrollen, die nicht vertrauenswürdige Änderungen während der Architektur- und Entwurfsphase verhindern. Validieren Sie, dass Versionsdaten schreibgeschützt bleiben und Zugriffskontrollen während der Testimplementierungsphase korrekt funktionieren. Verwenden Sie OTP-Fuses für Versionszähler. Implementieren Sie monotone Zähler, die nur inkrementiert werden können.

Häufige Auswirkungen

AuswirkungDetails
IntegritätBereich: Integrität

Roll-back auf verwundbare Firmware kompromittiert die Systemintegrität.
VertraulichkeitBereich: Vertraulichkeit

Ältere Firmware kann bekannte Schwachstellen haben, die Daten exponieren.
AuthentifizierungBereich: Authentifizierung

Downgrade-Angriffe können Sicherheitsverbesserungen in neueren Versionen umgehen.

Beispielcode und Lösung

Verwundbarer Code

// VERWUNDBAR: Änderbarer Sicherheitsversionszähler

module vulnerable_version_counter (
    input  wire        clk,
    input  wire        rst_n,
    input  wire [15:0] version_write_data,
    input  wire        version_write_en,
    output reg  [15:0] current_version,
    input  wire [15:0] firmware_version,
    input  wire        verify_firmware,
    output reg         firmware_allowed
);

    // VERWUNDBAR: Version in normalem Register gespeichert
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) current_version <= 16'h0001;
        else if (version_write_en) begin
            // VERWUNDBAR: Jeder Schreibzugriff erlaubt, einschließlich Downgrades
            current_version <= version_write_data;
        end
    end

    always @(posedge clk) begin
        if (verify_firmware) begin
            // VERWUNDBAR: Vergleich gegen änderbare Version
            firmware_allowed <= (firmware_version >= current_version);
        end
    end

    // Angriff:
    // 1. current_version = 10 (erfordert Firmware v10+)
    // 2. Angreifer setzt current_version = 1
    // 3. Alte verwundbare Firmware v5 besteht jetzt die Prüfung
    // 4. System bootet mit bekannten Schwachstellen

endmodule

Sichere Lösung

// SICHER: Unveränderlicher monotoner Sicherheitsversionszähler

module secure_version_counter (
    input  wire        clk,
    input  wire        rst_n,
    input  wire        version_increment,
    input  wire        privileged_access,
    input  wire        provisioning_mode,
    output wire [15:0] current_version,
    input  wire [15:0] firmware_version,
    input  wire        verify_firmware,
    output reg         firmware_allowed,
    output reg         version_update_denied
);

    // SICHER: OTP-Fuse-basierter Zähler (simuliert)
    reg [15:0] version_fuses;
    reg        version_locked;

    // SICHER: Gesetzte Bits zählen für Versionsnummer
    function [15:0] count_bits;
        input [15:0] fuses;
        integer i;
        begin
            count_bits = 0;
            for (i = 0; i < 16; i = i + 1)
                count_bits = count_bits + fuses[i];
        end
    endfunction

    assign current_version = count_bits(version_fuses);

    // SICHER: Version kann nur inkrementiert werden (monoton)
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            version_fuses <= 16'h0001;
            version_update_denied <= 1'b0;
            version_locked <= 1'b0;
        end else if (version_increment) begin
            version_update_denied <= 1'b0;

            if (!privileged_access) version_update_denied <= 1'b1;
            else if (version_locked) version_update_denied <= 1'b1;
            else begin
                // SICHER: Nächstes ungesetztes Bit finden und setzen (OTP-Verhalten)
                if (version_fuses[0] == 0) version_fuses[0] <= 1'b1;
                else if (version_fuses[1] == 0) version_fuses[1] <= 1'b1;
                // ... für alle Bits fortsetzen
                else if (version_fuses[15] == 0) version_fuses[15] <= 1'b1;
                else version_update_denied <= 1'b1;  // Maximale Version erreicht
            end
        end
    end

    // SICHER: Firmware-Versionsprüfung gegen unveränderlichen Zähler
    always @(posedge clk) begin
        if (verify_firmware)
            firmware_allowed <= (firmware_version >= current_version);
    end

endmodule
// SICHER: Sichere Versionsverwaltung mit Hardware-Unterstützung

#include <stdint.h>
#include <stdbool.h>

#define OTP_VERSION_ADDR    0x10000100

// SICHER: Version aus Hardware-OTP lesen (unveränderlich)
static uint16_t read_hardware_version(void) {
    volatile uint16_t* otp = (volatile uint16_t*)OTP_VERSION_ADDR;
    return *otp;
}

// SICHER: Version inkrementieren (kann nur steigen)
bool secure_increment_version(void) {
    uint16_t current = read_hardware_version();
    uint16_t new_version = current + 1;

    // SICHER: Sichere Hardware-API aufrufen um OTP zu programmieren
    if (!program_otp_version(new_version)) return false;
    return true;
}

// SICHER: Firmware-Version gegen Hardware-Zähler prüfen
bool secure_check_firmware_version(uint16_t firmware_version) {
    uint16_t required_version = read_hardware_version();
    return firmware_version >= required_version;
}

CVE-Beispiele

  • CVE-2020-0069: MediaTek-Chipsätze erlaubten Sicherheitsversions-Rollback und ermöglichten bekannte Exploits.
  • CVE-2019-11478: Linux-Kernel-TCP-Schwachstelle ausnutzbar durch Firmware-Rollback.

Verwandte CWEs

  • CWE-285: Improper Authorization (Eltern)
  • CWE-757: Selection of Less-Secure Algorithm During Negotiation (Peer)
  • CWE-1196: Security Flow Issues (Kategorie)

Referenzen

  1. MITRE Corporation. "CWE-1328: Security Version Number Mutable to Older Versions." https://cwe.mitre.org/data/definitions/1328.html
  2. ARM. "Trusted Firmware Anti-Rollback Protection"
  3. NIST. "Platform Firmware Resiliency Guidelines"