Internes Asset unsicherem Debug-Zugriffslevel oder -Zustand ausgesetzt

Beschreibung

Internes Asset unsicherem Debug-Zugriffslevel oder -Zustand ausgesetzt tritt auf, wenn ein Produkt physische Debug- oder Testschnittstellen mit mehreren Zugriffslevels verwendet, aber internen Assets falsche Debug-Zugriffsrechte zuweist, was unbeabsichtigten Zugriff von nicht vertrauenswürdigen Debug-Agenten ermöglicht. Die Debug-Autorisierung unterstützt mehrere Zugriffslevels, die steuern, welche System-Assets basierend auf authentifizierten Berechtigungen zugänglich sind. Die Autorisierung kann vom Systemzustand oder der Boot-Phase abhängen. Beispielsweise könnte ein vollständiger System-Debug-Zugriff nur früh im Boot nach einem System-Reset erlaubt sein, um sicherzustellen, dass Daten vorheriger Sitzungen nicht zugänglich sind.

Risiko

Falsche Debug-Zugriffslevels haben schwerwiegende Sicherheitsauswirkungen. Sensible Assets können auf falschen Berechtigungslevels zugänglich sein. Debug-Zugriff während falscher Boot-Phasen kann Geheimnisse offenlegen. Angreifer können den Boot-Ablauf über Debug ändern. Verschlüsselungsschlüssel können vor der Sperrung zugänglich sein. Speicherschutz kann über Debug umgangen werden. Daten vorheriger Sitzungen können zugänglich sein. Privilege Escalation kann über Debug möglich sein.

Lösung

Stellen Sie sicher, dass Debug-Zugriffslevels alle internen Assets korrekt schützen. Beschränken Sie den vollständigen Debug-Zugriff auf geeignete Boot-Phasen. Setzen Sie Debug-Schutzregister standardmäßig auf den gesicherten Zustand. Verwenden Sie UND-Logik statt ODER für die Kombination von Zugriffsüberprüfungen. Überprüfen Sie den Debug-Schutz über alle Systemzustände hinweg. Testen Sie den Debug-Zugriff in jeder Boot-Phase. Dokumentieren Sie die Debug-Zugriffsanforderungen für jedes Asset. Implementieren Sie eine ordnungsgemäße Debug-Authentifizierung.

Häufige Auswirkungen

AuswirkungDetails
VertraulichkeitUmfang: Vertraulichkeit

Speicher lesen - Angreifer könnten sensible Informationen aus internen Assets über einen Debugger erhalten, wenn Schutzmechanismen die korrekten Debug-Zugriffslevels nicht durchsetzen.
IntegritätUmfang: Integrität

Speicher ändern - Unbefugte Speicheränderung durch unzureichend geschützten Debug-Zugriff.
ZugriffskontrolleUmfang: Zugriffskontrolle

Schutzmechanismus umgehen, Berechtigungen erlangen - Autorisierungs- und Zugriffskontrollverletzungen ermöglichen unbefugte Privilegienannahme.

Beispielcode und Lösung

Verwundbarer Code

// VERWUNDBAR: JTAG-Zugriff vor Sicherheitsinitialisierung erlaubt

module vulnerable_jtag_protection (
    input wire clk,
    input wire reset_n,
    input wire jtag_request,
    input wire [31:0] jtag_addr,
    input wire jtag_write,
    input wire [31:0] jtag_wdata,
    input wire boot_complete,
    input wire security_init_done,
    output reg [31:0] jtag_rdata,
    output reg jtag_ack
);

    // JTAG-Schutzregister
    reg jtag_shield_enabled;

    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            // VERWUNDBAR: JTAG-Schutz standardmäßig deaktiviert!
            jtag_shield_enabled <= 1'b0;  // Sollte 1'b1 sein
        end
        else if (boot_complete) begin
            // Schutz erst nach Boot-Abschluss aktiviert
            // Zu spät - Angreifer kann während des Boots zugreifen
            jtag_shield_enabled <= 1'b1;
        end
    end

    // VERWUNDBAR: Voller JTAG-Zugriff vor boot_complete
    always @(posedge clk) begin
        if (jtag_request) begin
            if (!jtag_shield_enabled) begin
                // JTAG hat vollen Zugriff während des frühen Boots!
                if (jtag_write) begin
                    memory[jtag_addr] <= jtag_wdata;  // Kann Boot-Code ändern!
                end else begin
                    jtag_rdata <= memory[jtag_addr];  // Kann Schlüssel lesen!
                end
                jtag_ack <= 1'b1;
            end else begin
                jtag_ack <= 1'b0;  // Nach Boot blockiert
            end
        end
    end

    // Angriffsfenster: Von Reset bis boot_complete, voller Debug-Zugriff

endmodule

// VERWUNDBAR: Debug-Berechtigungsprüfung verwendet ODER statt UND
module vulnerable_debug_auth (
    input wire clk,
    input wire reset_n,
    input wire debug_request,
    input wire debug_mode_active,
    input wire user_mode,
    input wire password_correct,
    output reg debug_allowed
);

    // VERWUNDBAR: ODER-Logik - eine der Bedingungen reicht für Zugriff
    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            debug_allowed <= 1'b0;
        end
        else begin
            // Fehler: debug_mode_active ODER user_mode gewährt Zugriff
            // Sollte BEIDE Bedingungen erfordern
            debug_allowed <= debug_request && (debug_mode_active || password_correct);
        end
    end

    // Wenn debug_mode_active gesetzt ist (z.B. durch Ziehen eines Pins), kein Passwort nötig

endmodule

// VERWUNDBAR: Debug-Zugriffslevel nicht an Boot-Phase angepasst
module vulnerable_boot_debug (
    input wire clk,
    input wire reset_n,
    input wire [2:0] boot_stage,
    input wire debug_request,
    input wire [2:0] debug_access_level,
    input wire [31:0] debug_addr,
    output reg [31:0] debug_data,
    output reg debug_granted
);

    // Boot-Phasen
    parameter STAGE_ROM = 3'h0;
    parameter STAGE_BOOTLOADER = 3'h1;
    parameter STAGE_KERNEL = 3'h2;
    parameter STAGE_USER = 3'h3;

    // Debug-Zugriffslevels
    parameter ACCESS_NONE = 3'h0;
    parameter ACCESS_USER = 3'h1;
    parameter ACCESS_PRIVILEGED = 3'h2;
    parameter ACCESS_FULL = 3'h3;

    always @(posedge clk) begin
        if (debug_request) begin
            // VERWUNDBAR: Zugriffslevel nicht korrekt nach Boot-Phase eingeschränkt
            // Voller Zugriff selbst in späteren Boot-Phasen erlaubt
            if (debug_access_level == ACCESS_FULL) begin
                debug_data <= memory[debug_addr];
                debug_granted <= 1'b1;
            end
            else begin
                debug_granted <= 1'b0;
            end
        end
    end

    // Sollte vollen Zugriff nur auf frühes Boot beschränken

endmodule
// VERWUNDBAR: Debug-Zugriff während sensibler Boot-Operationen

void vulnerable_secure_boot(void) {
    // Verschlüsselungsschlüssel laden
    load_boot_keys();  // Schlüssel jetzt im Speicher

    // VERWUNDBAR: Debug noch aktiviert, Schlüssel zugänglich!

    // Firmware-Signatur überprüfen
    if (!verify_signature()) {
        // Boot fehlgeschlagen, aber Debug kann noch auf Schlüssel zugreifen
        halt();
    }

    // Debug schließlich deaktivieren...
    disable_debug();  // Zu spät - Schlüssel könnten bereits extrahiert worden sein
}

// VERWUNDBAR: Debug-Berechtigungsprüfung
bool vulnerable_debug_check(uint32_t addr) {
    // VERWUNDBAR: Debug während Boot immer erlauben
    if (!boot_complete) {
        return true;  // Voller Zugriff während des Boots
    }

    // Nach dem Boot Berechtigung prüfen
    return is_privileged_debug();
}

Sichere Lösung

// SICHER: JTAG-Schutz standardmäßig aktiviert

module secure_jtag_protection (
    input wire clk,
    input wire reset_n,
    input wire jtag_request,
    input wire [31:0] jtag_addr,
    input wire jtag_write,
    input wire [31:0] jtag_wdata,
    input wire jtag_authenticated,  // Erfordert Authentifizierung
    input wire boot_complete,
    input wire security_init_done,
    output reg [31:0] jtag_rdata,
    output reg jtag_ack,
    output reg jtag_denied
);

    // JTAG-Schutzregister
    reg jtag_shield_enabled;

    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            // SICHER: JTAG-Schutz standardmäßig AKTIVIERT
            jtag_shield_enabled <= 1'b1;
        end
        // Schutz kann nur mit Authentifizierung nach Sicherheitsinitialisierung deaktiviert werden
        else if (security_init_done && jtag_authenticated) begin
            // Authentifiziertes Debug nach Sicherheitskonfiguration erlauben
            jtag_shield_enabled <= 1'b0;
        end
    end

    // SICHER: JTAG blockiert bis authentifiziert
    always @(posedge clk) begin
        jtag_denied <= 1'b0;

        if (jtag_request) begin
            if (jtag_shield_enabled) begin
                // Debug blockiert
                jtag_rdata <= 32'h0;
                jtag_ack <= 1'b0;
                jtag_denied <= 1'b1;
            end
            else if (jtag_authenticated) begin
                // Authentifiziertes Debug erlaubt
                if (jtag_write) begin
                    memory[jtag_addr] <= jtag_wdata;
                end else begin
                    jtag_rdata <= memory[jtag_addr];
                end
                jtag_ack <= 1'b1;
            end
            else begin
                jtag_ack <= 1'b0;
                jtag_denied <= 1'b1;
            end
        end
    end

endmodule

// SICHER: Debug-Berechtigungsprüfung verwendet UND-Logik
module secure_debug_auth (
    input wire clk,
    input wire reset_n,
    input wire debug_request,
    input wire debug_mode_active,
    input wire user_authorized,
    input wire password_correct,
    output reg debug_allowed
);

    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            debug_allowed <= 1'b0;
        end
        else begin
            // SICHER: UND-Logik - ALLE Bedingungen erforderlich
            debug_allowed <= debug_request &&
                            debug_mode_active &&
                            user_authorized &&
                            password_correct;
        end
    end

endmodule

// SICHER: Debug-Zugriffslevel an Boot-Phase angepasst
module secure_boot_debug (
    input wire clk,
    input wire reset_n,
    input wire [2:0] boot_stage,
    input wire debug_request,
    input wire [2:0] debug_access_level,
    input wire debug_authenticated,
    input wire [31:0] debug_addr,
    output reg [31:0] debug_data,
    output reg debug_granted,
    output reg access_violation
);

    // Boot-Phasen
    parameter STAGE_ROM = 3'h0;
    parameter STAGE_BOOTLOADER = 3'h1;
    parameter STAGE_KERNEL = 3'h2;
    parameter STAGE_USER = 3'h3;

    // Debug-Zugriffslevels
    parameter ACCESS_NONE = 3'h0;
    parameter ACCESS_USER = 3'h1;
    parameter ACCESS_PRIVILEGED = 3'h2;
    parameter ACCESS_FULL = 3'h3;

    // Maximales erlaubtes Zugriffslevel pro Boot-Phase
    function [2:0] max_access_for_stage;
        input [2:0] stage;
        begin
            case (stage)
                STAGE_ROM: max_access_for_stage = ACCESS_NONE;      // Kein Debug während ROM
                STAGE_BOOTLOADER: max_access_for_stage = ACCESS_PRIVILEGED;  // Eingeschränkt
                STAGE_KERNEL: max_access_for_stage = ACCESS_PRIVILEGED;
                STAGE_USER: max_access_for_stage = ACCESS_USER;     // Nur Benutzerebene
                default: max_access_for_stage = ACCESS_NONE;
            endcase
        end
    endfunction

    always @(posedge clk) begin
        access_violation <= 1'b0;

        if (debug_request && debug_authenticated) begin
            // SICHER: Zugriffslevel für aktuelle Boot-Phase prüfen
            if (debug_access_level <= max_access_for_stage(boot_stage)) begin
                debug_data <= memory[debug_addr];
                debug_granted <= 1'b1;
            end
            else begin
                // Zugriffslevel zu hoch für aktuelle Boot-Phase
                debug_data <= 32'h0;
                debug_granted <= 1'b0;
                access_violation <= 1'b1;
            end
        end
        else begin
            debug_granted <= 1'b0;
        end
    end

endmodule
// SICHER: Debug während Secure Boot ordnungsgemäß eingeschränkt

void secure_boot_sequence(void) {
    // SICHER: Debug DEAKTIVIEREN, BEVOR Schlüssel geladen werden
    disable_debug_access();

    // Überprüfen, ob Debug deaktiviert ist
    if (is_debug_enabled()) {
        panic("Debug nicht während Secure Boot deaktiviert!");
    }

    // Jetzt sicher, Schlüssel zu laden
    load_boot_keys();

    // Firmware-Signatur überprüfen
    if (!verify_signature()) {
        // Schlüssel vor dem Anhalten löschen
        clear_boot_keys();
        halt();
    }

    // Schlüssel aus dem Speicher nach Verwendung löschen
    clear_boot_keys();

    // Debug kann nach dem Boot bei Bedarf wieder aktiviert werden
    // (mit ordnungsgemäßer Authentifizierung)
}

// SICHER: Debug-Berechtigung ordnungsgemäß geprüft
bool secure_debug_check(uint32_t addr, uint32_t access_level) {
    uint32_t current_stage = get_boot_stage();
    uint32_t max_level = get_max_debug_level(current_stage);

    // Authentifizierung prüfen
    if (!is_debug_authenticated()) {
        return false;
    }

    // Zugriffslevel für Boot-Phase prüfen
    if (access_level > max_level) {
        log_security_event("Debug-Zugriffslevel-Verletzung: %d > %d",
                          access_level, max_level);
        return false;
    }

    // Prüfen, ob Adresse auf diesem Level zugänglich ist
    if (!is_address_accessible(addr, access_level)) {
        return false;
    }

    return true;
}

uint32_t get_max_debug_level(uint32_t boot_stage) {
    switch (boot_stage) {
        case STAGE_ROM:
            return ACCESS_NONE;        // Kein Debug während ROM
        case STAGE_BOOTLOADER:
            return ACCESS_PRIVILEGED;  // Eingeschränkter Zugriff
        case STAGE_KERNEL:
            return ACCESS_PRIVILEGED;
        case STAGE_USER:
            return ACCESS_USER;        // Nur Benutzerebene
        default:
            return ACCESS_NONE;
    }
}

CVE-Beispiele

  • CVE-2019-18827: JTAG-Zugriff vor ROM-Code-Ausführung auf Barco ClickShare möglich
  • Schwachstellen im Debug-Modus des CVA6-Prozessors

Verwandte CWEs

  • CWE-863: Fehlerhafte Autorisierung (übergeordnet)
  • CWE-1191: On-Chip Debug- und Testschnittstelle mit unsachgemäßer Zugriffskontrolle (verwandt)
  • CWE-1243: Sensible nichtflüchtige Informationen nicht während Debug geschützt (verwandt)

Referenzen

  1. MITRE Corporation. "CWE-1244: Internal Asset Exposed to Unsafe Debug Access Level or State." https://cwe.mitre.org/data/definitions/1244.html
  2. REF-1377, REF-1378: CVA6 Processor Vulnerability Examples
  3. REF-1056: Barco ClickShare JTAG Vulnerabilities