Hardware ermöglicht Aktivierung von Test- oder Debug-Logik zur Laufzeit

Beschreibung

Hardware ermöglicht die Aktivierung von Test- oder Debug-Logik zur Laufzeit, wenn während der Laufzeit die Hardware die Aktivierung von Test- oder Debug-Logik (Funktionen) erlaubt, wodurch der Zustand der Hardware geändert werden kann. Diese Aktivierungsfähigkeit erzeugt Sicherheitsrisiken, indem sie Angreifern ermöglicht, das Systemverhalten zu ändern und auf sensible Informationen zuzugreifen. Beispiele umfassen Lese-/Schreibzugriff auf Systemdaten durch Testmodi, Datenänderung durch Fehlerinjektion während Bus-Operationen und unbefugten Zugriff auf Systemgeheimnisse.

Risiko

Laufzeit-Test-/Debug-Aktivierung hat schwerwiegende Auswirkungen. Speicheränderung möglich. Unbefugte Lesezugriffe ermöglicht. Denial of Service durch Instabilität. Unbefugte Code-Ausführung. Privilegienerweiterung. Umgehung von Schutzmechanismen. Ausführungslogik verändert. Leistung beeinträchtigt. Zuverlässigkeitsprobleme. Hardware-Zustand kompromittiert. Hohe Wahrscheinlichkeit wenn Testmodi zugänglich bleiben.

Lösung

Fügen Sie Einschränkungen ein, wann die Test- oder Debug-Funktionen der Hardware aktiviert werden können. Verhindern Sie privilegierten Moduszugriff während des normalen Betriebs. Beschränken Sie die Test-/Debug-Aktivierung auf spezifische Zeitfenster wie Boot oder Konfigurationsphasen. Deaktivieren Sie solche Funktionen während des Laufzeitbetriebs vollständig. Verwenden Sie Hardware-Fuses, um Testfunktionen in der Produktion dauerhaft zu deaktivieren. Fordern Sie Authentifizierung für die Debug-Aktivierung.

Häufige Auswirkungen

AuswirkungDetails
VertraulichkeitBereich: Vertraulichkeit

Systemgeheimnisse über Debug-Schnittstellen lesbar.
IntegritätBereich: Integrität

Speicher und Ausführungszustand über Testmodi modifizierbar.
VerfügbarkeitBereich: Verfügbarkeit

Denial of Service durch Abstürze, Instabilität oder Ressourcenerschöpfung.

Beispielcode und Lösung

Verwundbarer Code

// VERWUNDBAR: Testmodus zur Laufzeit aktivierbar

module vulnerable_test_controller (
    input  wire        clk,
    input  wire        rst_n,
    input  wire        test_mode_enable,   // Software-steuerbar!
    input  wire [31:0] test_addr,
    input  wire [31:0] test_wdata,
    input  wire        test_write,
    input  wire        test_read,

    // Systemschnittstellen
    output reg  [31:0] sys_addr,
    output reg  [31:0] sys_wdata,
    output reg         sys_write,
    output reg         sys_read,
    output reg  [31:0] sys_rdata,

    // Interner Debug-Zugriff
    output reg         debug_mem_access,
    output reg         error_inject_enable
);

    // VERWUNDBAR: Testmodus kann jederzeit aktiviert werden
    // Keine Einschränkungen wann oder wer ihn aktivieren kann

    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            debug_mem_access <= 1'b0;
            error_inject_enable <= 1'b0;
        end else begin
            // VERWUNDBAR: Testmodus gewährt spezielle Fähigkeiten
            if (test_mode_enable) begin
                // VERWUNDBAR: Direkter Speicherzugriff unter Umgehung des Schutzes
                sys_addr <= test_addr;
                sys_wdata <= test_wdata;
                sys_write <= test_write;
                sys_read <= test_read;

                // VERWUNDBAR: Debug-Funktionen zur Laufzeit aktiviert
                debug_mem_access <= 1'b1;
                error_inject_enable <= 1'b1;
            end else begin
                debug_mem_access <= 1'b0;
                error_inject_enable <= 1'b0;
            end
        end
    end

    // Angriff:
    // 1. Bösartige Software setzt test_mode_enable = 1
    // 2. Debug-Speicherzugriff aktiviert
    // 3. Angreifer liest/schreibt geschützten Speicher
    // 4. Fehlerinjektion beschädigt Systemzustand

endmodule

// VERWUNDBAR: Debug-Logik während des normalen Betriebs zugänglich
module vulnerable_cpu_debug (
    input  wire        clk,
    input  wire        rst_n,
    input  wire        debug_request,     // VERWUNDBAR: Immer verfügbar
    input  wire [31:0] debug_addr,
    input  wire [31:0] debug_data,
    input  wire        debug_write,

    // CPU-Interna (sollten geschützt sein)
    output reg  [31:0] pc_override,
    output reg         halt_cpu,
    output reg         single_step,
    output reg  [31:0] register_write_data,
    output reg  [4:0]  register_write_addr,
    output reg         register_write_en
);

    // VERWUNDBAR: Keine Lebenszyklus-Zustandsprüfung
    // Debug auch nach Abschluss von Secure Boot zugänglich

    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            halt_cpu <= 1'b0;
            single_step <= 1'b0;
            register_write_en <= 1'b0;
        end else if (debug_request) begin
            // VERWUNDBAR: Debug-Befehle werden zur Laufzeit verarbeitet

            case (debug_addr[7:0])
                8'h00: begin
                    // CPU anhalten
                    halt_cpu <= debug_data[0];
                end
                8'h04: begin
                    // Programmzähler überschreiben
                    pc_override <= debug_data;  // VERWUNDBAR!
                end
                8'h08: begin
                    // CPU-Register schreiben
                    register_write_addr <= debug_data[4:0];
                    register_write_data <= debug_data;
                    register_write_en <= 1'b1;  // VERWUNDBAR!
                end
                8'h0C: begin
                    // Einzelschritt-Modus aktivieren
                    single_step <= debug_data[0];
                end
            endcase
        end
    end

    // VERWUNDBAR: Keine Authentifizierung erforderlich
    // VERWUNDBAR: Keine Lebenszyklus-Prüfung (Produktion vs. Entwicklung)

endmodule

// VERWUNDBAR: BIST zur Laufzeit zugänglich
module vulnerable_bist_controller (
    input  wire        clk,
    input  wire        rst_n,
    input  wire        bist_start,        // Software-auslösbar
    input  wire [7:0]  bist_pattern,
    output reg         bist_running,
    output reg         bist_complete,
    output reg         bist_pass
);

    reg [31:0] memory [0:1023];
    reg [9:0] test_addr;

    // VERWUNDBAR: BIST kann jederzeit gestartet werden
    // Dies kann Speicher während des normalen Betriebs beschädigen!

    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            bist_running <= 1'b0;
            bist_complete <= 1'b0;
        end else if (bist_start && !bist_running) begin
            // VERWUNDBAR: BIST zerstört Speicherinhalte!
            bist_running <= 1'b1;
            test_addr <= 10'b0;
        end else if (bist_running) begin
            // VERWUNDBAR: Überschreibt Live-Speicher mit Testmustern
            memory[test_addr] <= {4{bist_pattern}};
            test_addr <= test_addr + 1;

            if (test_addr == 10'h3FF) begin
                bist_complete <= 1'b1;
                bist_running <= 1'b0;
            end
        end
    end

    // Angriff:
    // BIST während der Laufzeit auslösen um kritische Daten zu beschädigen
    // Verursacht Denial of Service oder ausnutzbaren Zustand

endmodule

Sichere Lösung

// SICHER: Testmodus mit Lebenszyklus-Einschränkungen

module secure_test_controller (
    input  wire        clk,
    input  wire        rst_n,
    input  wire        test_mode_request,
    input  wire [31:0] test_addr,
    input  wire [31:0] test_wdata,
    input  wire        test_write,
    input  wire        test_read,

    // Lebenszyklus-Signale
    input  wire        boot_complete,         // Gesetzt wenn Boot abgeschlossen
    input  wire        production_mode_fuse,  // OTP-Fuse für Produktion

    // Systemschnittstellen
    output reg  [31:0] sys_addr,
    output reg  [31:0] sys_wdata,
    output reg         sys_write,
    output reg         sys_read,
    output reg  [31:0] sys_rdata,

    // Debug-Zugriff (eingeschränkt)
    output reg         debug_mem_access,
    output reg         error_inject_enable,
    output reg         test_mode_denied
);

    // SICHER: Testmodus nur während spezifischer Lebenszyklusphasen erlaubt
    wire test_allowed = !boot_complete &&      // Nur vor Boot-Abschluss
                        !production_mode_fuse; // Nur im Entwicklungsmodus

    // SICHER: Tatsächlicher Testmodus-Zustand
    reg test_mode_active;

    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            test_mode_active <= 1'b0;
            debug_mem_access <= 1'b0;
            error_inject_enable <= 1'b0;
            test_mode_denied <= 1'b0;
        end else begin
            test_mode_denied <= 1'b0;

            // SICHER: Prüfen ob Testmodus-Aktivierung erlaubt ist
            if (test_mode_request) begin
                if (test_allowed) begin
                    test_mode_active <= 1'b1;
                end else begin
                    // SICHER: Testmodus nach Boot oder in Produktion ablehnen
                    test_mode_active <= 1'b0;
                    test_mode_denied <= 1'b1;
                end
            end

            // SICHER: Testfunktionen nur aktiv wenn erlaubt
            if (test_mode_active && test_allowed) begin
                sys_addr <= test_addr;
                sys_wdata <= test_wdata;
                sys_write <= test_write;
                sys_read <= test_read;
                debug_mem_access <= 1'b1;
                error_inject_enable <= 1'b1;
            end else begin
                // SICHER: Testfunktionen deaktivieren wenn nicht erlaubt
                debug_mem_access <= 1'b0;
                error_inject_enable <= 1'b0;
                test_mode_active <= 1'b0;
            end
        end
    end

    // SICHER: Testmodus nach Boot-Abschluss erzwungen deaktivieren
    always @(posedge boot_complete) begin
        test_mode_active <= 1'b0;
    end

endmodule

// SICHER: Debug-Logik mit Authentifizierung und Lebenszyklus-Prüfung
module secure_cpu_debug (
    input  wire        clk,
    input  wire        rst_n,
    input  wire        debug_request,
    input  wire [31:0] debug_addr,
    input  wire [31:0] debug_data,
    input  wire        debug_write,

    // SICHER: Lebenszyklus und Authentifizierung
    input  wire        debug_authenticated,   // Challenge-Response abgeschlossen
    input  wire        development_mode,      // Von Fuse
    input  wire [1:0]  lifecycle_state,       // 00=Entw, 01=Prod, 10=RMA, 11=Verschrottet

    // CPU-Interna
    output reg  [31:0] pc_override,
    output reg         halt_cpu,
    output reg         single_step,
    output reg  [31:0] register_write_data,
    output reg  [4:0]  register_write_addr,
    output reg         register_write_en,
    output reg         debug_denied
);

    // SICHER: Debug nur mit ordnungsgemäßer Authentifizierung und Lebenszyklus erlaubt
    localparam LC_DEV = 2'b00;
    localparam LC_PROD = 2'b01;
    localparam LC_RMA = 2'b10;

    wire debug_allowed;

    // SICHER: Unterschiedliche Fähigkeiten pro Lebenszyklus-Zustand
    assign debug_allowed = (lifecycle_state == LC_DEV) ||
                           (lifecycle_state == LC_RMA && debug_authenticated);
    // Produktionsmodus erlaubt niemals Debug

    // SICHER: Fähigkeiten auch wenn erlaubt einschränken
    wire full_debug = (lifecycle_state == LC_DEV);
    wire limited_debug = (lifecycle_state == LC_RMA && debug_authenticated);

    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            halt_cpu <= 1'b0;
            single_step <= 1'b0;
            register_write_en <= 1'b0;
            debug_denied <= 1'b0;
        end else begin
            register_write_en <= 1'b0;
            debug_denied <= 1'b0;

            if (debug_request) begin
                if (!debug_allowed) begin
                    // SICHER: Debug in Produktion ablehnen
                    debug_denied <= 1'b1;
                end else begin
                    case (debug_addr[7:0])
                        8'h00: begin
                            // CPU anhalten - in Debug-Modi erlaubt
                            halt_cpu <= debug_data[0];
                        end

                        8'h04: begin
                            // PC-Überschreibung - nur im vollen Debug
                            if (full_debug) begin
                                pc_override <= debug_data;
                            end else begin
                                debug_denied <= 1'b1;
                            end
                        end

                        8'h08: begin
                            // Register-Schreiben - nur im vollen Debug
                            if (full_debug) begin
                                register_write_addr <= debug_data[4:0];
                                register_write_data <= debug_data;
                                register_write_en <= 1'b1;
                            end else begin
                                debug_denied <= 1'b1;
                            end
                        end

                        8'h0C: begin
                            // Einzelschritt - im eingeschränkten Debug erlaubt
                            single_step <= debug_data[0];
                        end

                        default: begin
                            debug_denied <= 1'b1;
                        end
                    endcase
                end
            end
        end
    end

endmodule

// SICHER: BIST mit Laufzeit-Sperre
module secure_bist_controller (
    input  wire        clk,
    input  wire        rst_n,
    input  wire        bist_start,
    input  wire [7:0]  bist_pattern,
    input  wire        boot_complete,        // SICHER: Lebenszyklus-Signal
    input  wire        bist_unlock_fuse,     // SICHER: Spezielle Entsperr-Fuse
    output reg         bist_running,
    output reg         bist_complete,
    output reg         bist_pass,
    output reg         bist_denied
);

    reg [31:0] memory [0:1023];
    reg [9:0] test_addr;

    // SICHER: BIST nur vor Boot-Abschluss erlaubt
    wire bist_allowed = !boot_complete || bist_unlock_fuse;

    // SICHER: BIST nach Abschluss sperren
    reg bist_locked;

    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            bist_running <= 1'b0;
            bist_complete <= 1'b0;
            bist_locked <= 1'b0;
            bist_denied <= 1'b0;
        end else begin
            bist_denied <= 1'b0;

            if (bist_start && !bist_running) begin
                // SICHER: Prüfen ob BIST erlaubt ist
                if (bist_allowed && !bist_locked) begin
                    bist_running <= 1'b1;
                    test_addr <= 10'b0;
                end else begin
                    // SICHER: BIST nach Boot oder bei Sperre ablehnen
                    bist_denied <= 1'b1;
                end
            end else if (bist_running) begin
                // BIST ausführen (nur erreichbar wenn erlaubt)
                memory[test_addr] <= {4{bist_pattern}};
                test_addr <= test_addr + 1;

                if (test_addr == 10'h3FF) begin
                    bist_complete <= 1'b1;
                    bist_running <= 1'b0;
                    // SICHER: BIST nach Abschluss sperren
                    bist_locked <= 1'b1;
                end
            end
        end
    end

    // SICHER: Auch bei Boot-Abschluss sperren
    always @(posedge boot_complete) begin
        if (!bist_unlock_fuse) begin
            bist_locked <= 1'b1;
        end
    end

endmodule

CVE-Beispiele

  • CVE-2021-33150: Prozessor ermöglicht Test- oder Debug-Logik-Aktivierung zur Laufzeit.
  • CVE-2021-0146: Prozessor-Debug-Logik ermöglicht Privilegienerweiterung während des Betriebs.
  • CVE-2019-0090: Intel-CSME-Testmodus nach Secure Boot zugänglich.

Verwandte CWEs

  • CWE-284: Improper Access Control (Eltern)
  • CWE-1207: Debug and Test Problems (Kategorie)
  • CWE-1244: Internal Asset Exposed to Unsafe Debug Access (verwandt)
  • CWE-1243: Sensitive Non-Volatile Information Not Protected During Debug (verwandt)

Referenzen

  1. MITRE Corporation. "CWE-1313: Hardware Allows Activation of Test or Debug Logic at Runtime." https://cwe.mitre.org/data/definitions/1313.html
  2. NIST. "Platform Firmware Resiliency Guidelines"
  3. ARM. "CoreSight Debug and Trace Architecture"