Fehlende Quellenkennung in Entity-Transaktionen auf einem System-on-Chip (SOC)

Beschreibung

Fehlende Quellenkennung in Entity-Transaktionen auf einem System-on-Chip tritt auf, wenn ein Produkt einen Sicherheitskennungs-Mechanismus implementiert, aber Transaktionen ohne Sicherheitskennung sendet. In SoC-Umgebungen stammen Transaktionen von integrierten Schaltkreisen und Hardware-Engines, um auf Assets zuzugreifen oder Aktionen auszuführen. Diese Transaktionen beinhalten typischerweise Quellenidentität, Zielidentität und Sicherheitskennungen, die Zielagenten helfen zu bestimmen, welche Aktionen erlaubt sind. Wenn Quellagenten nicht konsistent die notwendige Sicherheitskennung mit der Transaktion einschließen, können Zielagenten entweder Nachrichten verwerfen (was Denial-of-Service verursacht) oder unangemessene Standardaktionen ausführen, was zu Privilege Escalation oder unbeabsichtigtem Zugriff führt.

Risiko

Fehlende Sicherheitskennungen haben schwerwiegende Auswirkungen. Speichermodifikation möglich. Unautorisierte Lesezugriffe ermöglicht. Systemabstürze durch abgelehnte Transaktionen. Schutzmechanismen umgangen. Unautorisierte Codeausführung. Privilege Escalation durch Standardaktionen. Denial of Service wenn Transaktionen verworfen werden. Hohe Ausnutzungswahrscheinlichkeit wenn Kennungen weggelassen werden.

Lösung

Überprüfen Sie Transaktionsdetails auf Designinkonsistenzen und häufige Schwächen während der Architektur- und Designphase. Stellen Sie sicher, dass alle Transaktionsquellen entsprechende Sicherheitskennungen einschließen. Testen Sie Sicherheitskennungs-Definition und Programmierfluss während Pre-Silicon- und Post-Silicon-Tests. Implementieren Sie Default-Deny-Richtlinien für Transaktionen ohne Kennungen. Validieren Sie Kennungspräsenz bei Zielagenten.

Häufige Auswirkungen

AuswirkungDetails
VertraulichkeitScope: Vertraulichkeit

Unautorisierter Lesezugriff wenn fehlende Kennung Standardzugriff erlaubt.
IntegritätScope: Integrität

Speichermodifikation durch Transaktionen ohne ordnungsgemäße Identifikation.
VerfügbarkeitScope: Verfügbarkeit

Denial of Service wenn Transaktionen wegen fehlender Kennungen verworfen werden.
ZugriffskontrolleScope: Zugriffskontrolle

Schutzumgehung, Privilege Escalation durch unangemessene Standardwerte.

Beispielcode und Lösung

Verwundbarer Code

// VERWUNDBAR: Transaktionsquelle ohne Sicherheitskennung

module vulnerable_transaction_source (
    input  wire        clk,
    input  wire        rst_n,
    input  wire        request,
    input  wire [31:0] address,
    input  wire [31:0] write_data,
    input  wire        write_enable,

    // Transaktionsbus-Ausgänge
    output reg  [31:0] bus_addr,
    output reg  [31:0] bus_data,
    output reg         bus_write,
    output reg         bus_valid
    // VERWUNDBAR: Keine Sicherheitskennungs-Ausgabe!
);

    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            bus_addr <= 32'b0;
            bus_data <= 32'b0;
            bus_write <= 1'b0;
            bus_valid <= 1'b0;
        end else if (request) begin
            bus_addr <= address;
            bus_data <= write_data;
            bus_write <= write_enable;
            bus_valid <= 1'b1;
            // VERWUNDBAR: Sicherheitskennung wird nicht mit Transaktion gesendet
            // Ziel weiß nicht, wer die Anfrage stellt
        end else begin
            bus_valid <= 1'b0;
        end
    end

endmodule

// VERWUNDBAR: Ziel akzeptiert Transaktionen ohne Kennung
module vulnerable_aes_key_register (
    input  wire        clk,
    input  wire        rst_n,
    input  wire [31:0] bus_addr,
    input  wire [31:0] bus_data,
    input  wire        bus_write,
    input  wire        bus_valid,
    // VERWUNDBAR: Keine Sicherheitskennungs-Eingabe
    output reg  [127:0] aes_key,
    output reg         access_granted
);

    localparam AES_KEY_ADDR = 32'h0000_F000;
    localparam REQUIRED_SECURITY_ID = 8'h02;  // Erforderlich aber nicht geprüft!

    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            aes_key <= 128'b0;
            access_granted <= 1'b0;
        end else if (bus_valid && bus_write) begin
            if (bus_addr == AES_KEY_ADDR) begin
                // VERWUNDBAR: Keine Sicherheitskennung zum Prüfen!
                // Entweder lehnt alle ab (DoS) oder akzeptiert alle (Privilege Escalation)

                // Option 1: Standard akzeptieren (VERWUNDBAR)
                aes_key[31:0] <= bus_data;
                access_granted <= 1'b1;

                // Option 2: Standard ablehnen (DoS für legitime Anfragen)
                // access_granted <= 1'b0;
            end
        end
    end

endmodule

// VERWUNDBAR: DMA-Engine ohne Sicherheitskennung
module vulnerable_dma_engine (
    input  wire        clk,
    input  wire        rst_n,
    input  wire        start_transfer,
    input  wire [31:0] src_addr,
    input  wire [31:0] dst_addr,
    input  wire [15:0] length,

    // Speicherschnittstelle
    output reg  [31:0] mem_addr,
    output reg  [31:0] mem_data,
    output reg         mem_read,
    output reg         mem_write
    // VERWUNDBAR: Keine security_id-Ausgabe
);

    reg [15:0] byte_counter;
    reg transferring;

    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            mem_addr <= 32'b0;
            mem_read <= 1'b0;
            mem_write <= 1'b0;
            transferring <= 1'b0;
        end else if (start_transfer && !transferring) begin
            transferring <= 1'b1;
            byte_counter <= 16'b0;
        end else if (transferring) begin
            // VERWUNDBAR: DMA-Transaktionen haben keine Sicherheitskennung
            // Speichercontroller kann nicht bestimmen, ob DMA Zugriff haben sollte
            // Könnte ausgenutzt werden, um auf geschützten Speicher zuzugreifen

            mem_addr <= src_addr + byte_counter;
            mem_read <= 1'b1;

            // Transfer läuft ohne Identität weiter...
        end
    end

endmodule

Sichere Lösung

// SICHER: Transaktionsquelle mit Sicherheitskennung

module secure_transaction_source #(
    parameter SECURITY_ID = 8'h02  // Konfigurierbares Sicherheitslevel
) (
    input  wire        clk,
    input  wire        rst_n,
    input  wire        request,
    input  wire [31:0] address,
    input  wire [31:0] write_data,
    input  wire        write_enable,

    // Transaktionsbus-Ausgänge
    output reg  [31:0] bus_addr,
    output reg  [31:0] bus_data,
    output reg         bus_write,
    output reg         bus_valid,
    output reg  [7:0]  bus_security_id  // SICHER: Sicherheitskennungs-Ausgabe
);

    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            bus_addr <= 32'b0;
            bus_data <= 32'b0;
            bus_write <= 1'b0;
            bus_valid <= 1'b0;
            bus_security_id <= 8'b0;
        end else if (request) begin
            bus_addr <= address;
            bus_data <= write_data;
            bus_write <= write_enable;
            bus_valid <= 1'b1;
            // SICHER: Sicherheitskennung bei jeder Transaktion einschließen
            bus_security_id <= SECURITY_ID;
        end else begin
            bus_valid <= 1'b0;
            bus_security_id <= 8'b0;
        end
    end

endmodule

// SICHER: Ziel validiert Sicherheitskennung
module secure_aes_key_register (
    input  wire        clk,
    input  wire        rst_n,
    input  wire [31:0] bus_addr,
    input  wire [31:0] bus_data,
    input  wire        bus_write,
    input  wire        bus_valid,
    input  wire [7:0]  bus_security_id,  // SICHER: Sicherheitskennungs-Eingabe
    output reg  [127:0] aes_key,
    output reg         access_granted,
    output reg         access_denied
);

    localparam AES_KEY_ADDR = 32'h0000_F000;
    localparam REQUIRED_SECURITY_ID = 8'h02;

    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            aes_key <= 128'b0;
            access_granted <= 1'b0;
            access_denied <= 1'b0;
        end else begin
            access_granted <= 1'b0;
            access_denied <= 1'b0;

            if (bus_valid && bus_write) begin
                if (bus_addr == AES_KEY_ADDR) begin
                    // SICHER: Prüfen, ob Sicherheitskennung vorhanden und gültig ist
                    if (bus_security_id == 8'b0) begin
                        // SICHER: Transaktionen ohne Kennung ablehnen
                        access_denied <= 1'b1;
                        // Sicherheitsereignis protokollieren
                    end else if (bus_security_id >= REQUIRED_SECURITY_ID) begin
                        // SICHER: Ordnungsgemäße Autorisierungsprüfung
                        aes_key[31:0] <= bus_data;
                        access_granted <= 1'b1;
                    end else begin
                        // SICHER: Unzureichende Berechtigung
                        access_denied <= 1'b1;
                    end
                end
            end
        end
    end

endmodule

// SICHER: DMA-Engine mit Sicherheitskennung
module secure_dma_engine #(
    parameter DMA_SECURITY_ID = 8'h01  // DMA-Sicherheitslevel
) (
    input  wire        clk,
    input  wire        rst_n,
    input  wire        start_transfer,
    input  wire [31:0] src_addr,
    input  wire [31:0] dst_addr,
    input  wire [15:0] length,
    input  wire [7:0]  requestor_security_id,  // SICHER: Wer DMA angefordert hat

    // Speicherschnittstelle
    output reg  [31:0] mem_addr,
    output reg  [31:0] mem_data,
    output reg         mem_read,
    output reg         mem_write,
    output reg  [7:0]  mem_security_id  // SICHER: Sicherheits-ID für Speicherzugriff
);

    reg [15:0] byte_counter;
    reg transferring;
    reg [7:0] active_security_id;

    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            mem_addr <= 32'b0;
            mem_read <= 1'b0;
            mem_write <= 1'b0;
            mem_security_id <= 8'b0;
            transferring <= 1'b0;
            active_security_id <= 8'b0;
        end else if (start_transfer && !transferring) begin
            transferring <= 1'b1;
            byte_counter <= 16'b0;
            // SICHER: Minimum von DMA- und Anforderer-Sicherheitslevel verwenden
            // DMA kann nicht mehr Zugriff gewähren als der Anforderer hat
            active_security_id <= (requestor_security_id < DMA_SECURITY_ID) ?
                                   requestor_security_id : DMA_SECURITY_ID;
        end else if (transferring) begin
            // SICHER: Sicherheitskennung bei DMA-Transaktionen einschließen
            mem_addr <= src_addr + byte_counter;
            mem_read <= 1'b1;
            mem_security_id <= active_security_id;  // SICHER: Ordnungsgemäße Identität

            // Speichercontroller kann nun Zugriffskontrolle durchsetzen
        end else begin
            mem_security_id <= 8'b0;
        end
    end

endmodule

// SICHER: Bus-Interconnect, der Kennungspräsenz validiert
module secure_bus_interconnect (
    input  wire        clk,
    input  wire        rst_n,

    // Quellschnittstelle
    input  wire [31:0] src_addr,
    input  wire [31:0] src_data,
    input  wire        src_write,
    input  wire        src_valid,
    input  wire [7:0]  src_security_id,

    // Zielschnittstelle
    output reg  [31:0] dst_addr,
    output reg  [31:0] dst_data,
    output reg         dst_write,
    output reg         dst_valid,
    output reg  [7:0]  dst_security_id,

    // Fehlersignale
    output reg         missing_id_error
);

    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            dst_valid <= 1'b0;
            missing_id_error <= 1'b0;
        end else if (src_valid) begin
            // SICHER: Validieren, dass Sicherheitskennung vorhanden ist
            if (src_security_id == 8'b0) begin
                // SICHER: Transaktionen ohne Kennung blockieren
                dst_valid <= 1'b0;
                missing_id_error <= 1'b1;

                // Verletzung für Sicherheitsüberwachung protokollieren
            end else begin
                // SICHER: Gültige Transaktion mit Kennung weiterleiten
                dst_addr <= src_addr;
                dst_data <= src_data;
                dst_write <= src_write;
                dst_valid <= 1'b1;
                dst_security_id <= src_security_id;
                missing_id_error <= 1'b0;
            end
        end else begin
            dst_valid <= 1'b0;
            missing_id_error <= 1'b0;
        end
    end

endmodule

CVE-Beispiele

  • CVE-2021-0146: Fehlende Sicherheitskennung in bestimmten Intel-Prozessoren ermöglichte Privilege Escalation durch Bus-Transaktionen.
  • CVE-2020-8705: SoC-Transaktionen ohne ordnungsgemäße Identifikation ermöglichten unautorisierten Zugriff.

Verwandte CWEs

  • CWE-1294: Insecure Security Identifier Mechanism (übergeordnet)
  • CWE-1198: Privilege Separation and Access Control Issues (Kategorie)
  • CWE-1290: Incorrect Decoding of Security Identifiers (verwandt)
  • CWE-862: Missing Authorization (verwandt)

Referenzen

  1. MITRE Corporation. "CWE-1302: Missing Source Identifier in Entity Transactions on a System-On-Chip (SOC)." https://cwe.mitre.org/data/definitions/1302.html
  2. ARM. "AMBA Protocol Security Extensions"
  3. RISC-V. "Physical Memory Protection (PMP) Specification"