Fehlerhafte Konvertierung von Sicherheitskennungen

Beschreibung

Fehlerhafte Konvertierung von Sicherheitskennungen tritt auf, wenn die Zuordnung von Bus-Transaktionssignalen zu Sicherheitskennungen eines Produkts Konvertierungsfehler enthält, die es nicht vertrauenswürdigen Agenten potenziell ermöglichen, unbefugten Zugriff auf Assets zu erhalten. In System-on-Chip (SoC)-Umgebungen tragen Transaktionen zwischen integrierten Schaltungen Quell- und Zielidentitäten zusammen mit Sicherheitskennungen, die es Zielagenten ermöglichen, Zugriffskontrollen durchzusetzen. Protokollbrücken, die inkompatible Bustypen verbinden (z.B. AHB-zu-OCP, APB-zu-AXI), müssen Sicherheitskennungsinformationen zwischen Protokollen korrekt übersetzen. Wenn diese Brücken Sicherheitskennungen falsch konvertieren, können nicht vertrauenswürdige Agenten Zugriffsbeschränkungen umgehen.

Risiko

Fehlerhafte Konvertierung von Sicherheitskennungen hat schwerwiegende Auswirkungen. Nicht vertrauenswürdige Agenten umgehen Zugriffskontrollen. Speichermodifikation möglich. Unbefugte Lesezugriffe aktiviert. Denial-of-Service-Angriffe. Ausführung von unbefugtem Code. Privilegieneskalation. Identitätsübernahme. Vollständige Umgehung der Zugriffskontrollrichtlinien. Hohe Ausnutzungswahrscheinlichkeit wenn Protokollbrücken Konvertierungsfehler haben.

Lösung

Konvertierer/Brücken für Sicherheitskennungen erfordern eine Designüberprüfung auf Inkonsistenz und häufige Schwachstellen während der Architektur- und Entwurfsphase. Stellen Sie sicher, dass Protokollzuordnungen die Sicherheitssemantik beibehalten. Zugriffs- und Programmierabläufe müssen in Pre-Silicon- und Post-Silicon-Tests getestet werden. Erstellen Sie umfassende Testvektoren, die alle Sicherheitskennungswerte über Protokollgrenzen hinweg abdecken. Verwenden Sie formale Verifikation, um die Konvertierungskorrektheit zu beweisen. Dokumentieren Sie Sicherheitskennungszuordnungen explizit.

Häufige Auswirkungen

AuswirkungDetails
VertraulichkeitBereich: Vertraulichkeit

Unbefugter Lesezugriff auf geschützten Speicher und Assets.
IntegritätBereich: Integrität

Speichermodifikation durch nicht vertrauenswürdige Agenten über Protokollbrücke.
VerfügbarkeitBereich: Verfügbarkeit

Denial of Service durch Ressourcenverbrauch.
ZugriffskontrolleBereich: Zugriffskontrolle

Privilegieneskalation und Identitätsübernahme durch fehlerhafte Zuordnung.

Beispielcode und Lösung

Verwundbarer Code

// VERWUNDBAR: AHB-zu-OCP-Brücke mit fehlerhafter Sicherheits-ID-Konvertierung

module vulnerable_ahb_to_ocp_bridge (
    input  wire        clk,
    input  wire        rst_n,

    // AHB-Signale
    input  wire [31:0] ahb_haddr,
    input  wire [2:0]  ahb_hburst,
    input  wire [3:0]  ahb_hprot,      // AHB-Schutzsignale
    input  wire        ahb_hwrite,
    input  wire [31:0] ahb_hwdata,
    input  wire [1:0]  ahb_htrans,

    // OCP-Signale
    output reg  [31:0] ocp_maddr,
    output reg  [2:0]  ocp_mburstlength,
    output reg  [1:0]  ocp_mcmd,
    output reg  [31:0] ocp_mdata,
    output reg  [7:0]  ocp_mtagid,     // OCP-Sicherheitstag
    output reg         ocp_mreqinfo    // OCP-Sicherheitsinfo
);

    // AHB HPROT-Bits:
    // [0] = Daten/Opcode (1=Daten, 0=Opcode)
    // [1] = Privilegiert (1=privilegiert, 0=Benutzer)
    // [2] = Pufferbar
    // [3] = Cachebar

    // OCP-Sicherheitsmodell (Beispiel):
    // mtagid[7:6] = Sicherheitsstufe (00=nicht vertrauenswürdig, 01=Benutzer, 10=priv, 11=sicher)
    // mtagid[5:0] = Master-ID

    // VERWUNDBAR: Fehlerhafte Konvertierung der Sicherheitskennungen
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            ocp_maddr <= 32'b0;
            ocp_mtagid <= 8'b0;
        end else begin
            ocp_maddr <= ahb_haddr;

            // VERWUNDBAR: Nur Bit [1] von hprot wird geprüft
            // Fehlendes Bit [3], das in einigen Implementierungen sicheren Zugriff anzeigt
            if (ahb_hprot[1]) begin
                ocp_mtagid[7:6] <= 2'b10;  // Privilegiert
            end else begin
                ocp_mtagid[7:6] <= 2'b01;  // Benutzer
            end

            // VERWUNDBAR: Master-ID nicht korrekt konvertiert
            // AHB hat keine explizite Master-ID, aber OCP erfordert sie
            ocp_mtagid[5:0] <= 6'b000000;  // Alle Master auf ID 0 abgebildet!
        end
    end

    // VERWUNDBAR: Sicherheitsinfo-Bit nicht korrekt gesetzt
    always @(*) begin
        // Sollte sicher/nicht-sicher basierend auf Bus-Master anzeigen
        ocp_mreqinfo = 1'b0;  // Zeigt immer nicht-sicher an!
    end

endmodule

// VERWUNDBAR: APB-zu-AXI-Brücke mit Sicherheitszuordnungsproblemen
module vulnerable_apb_to_axi_bridge (
    input  wire        clk,
    input  wire        rst_n,

    // APB-Signale
    input  wire [31:0] paddr,
    input  wire        pwrite,
    input  wire [31:0] pwdata,
    input  wire        psel,
    input  wire        penable,
    input  wire [2:0]  pprot,          // APB-Schutz

    // AXI-Signale
    output reg  [31:0] axi_awaddr,
    output reg  [2:0]  axi_awprot,     // AXI-Schutz
    output reg  [3:0]  axi_awcache,
    output reg  [31:0] axi_wdata,
    output reg         axi_awvalid
);

    // APB PPROT:
    // [0] = Normal/Privilegiert
    // [1] = Sicher/Nicht-sicher
    // [2] = Daten/Instruktion

    // AXI AWPROT:
    // [0] = Privilegiert
    // [1] = Nicht-sicher
    // [2] = Instruktion

    // VERWUNDBAR: Fehlerhafte Bit-Zuordnung zwischen Protokollen
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            axi_awprot <= 3'b0;
        end else begin
            // VERWUNDBAR: Bits sind an verschiedenen Positionen!
            // APB pprot[0] ist Privileg, aber direktes Kopieren
            axi_awprot <= pprot;  // FALSCH! Bit-Positionen stimmen nicht überein!

            // Korrekte Zuordnung sollte sein:
            // axi_awprot[0] = pprot[0]  (Privileg stimmt überein)
            // axi_awprot[1] = ~pprot[1] (APB sicher=0, AXI nicht-sicher=0, INVERTIERT!)
            // axi_awprot[2] = pprot[2]  (Daten/Instruktion stimmt überein)
        end
    end

endmodule
// VERWUNDBAR: Software-Brücke mit Sicherheits-ID-Konvertierungsproblemen

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

// Protokoll-A-Sicherheitsstufen
#define PROTO_A_UNTRUSTED  0x00
#define PROTO_A_USER       0x01
#define PROTO_A_SUPERVISOR 0x02
#define PROTO_A_SECURE     0x03

// Protokoll-B-Sicherheitsstufen (ändere Kodierung)
#define PROTO_B_PUBLIC     0x00
#define PROTO_B_NORMAL     0x04
#define PROTO_B_PRIVILEGED 0x08
#define PROTO_B_HYPERVISOR 0x0C

// VERWUNDBAR: Fehlerhafte Zuordnungstabelle
uint8_t vulnerable_convert_security_id(uint8_t proto_a_id) {
    // VERWUNDBAR: Direktes Kopieren der Werte - Kodierungen stimmen nicht überein!
    return proto_a_id;  // Werte bedeuten verschiedene Dinge!

    // PROTO_A_USER (0x01) wird zu PROTO_B_PUBLIC (0x00 + etwas)
    // Sicherheitssemantik geht verloren!
}

// VERWUNDBAR: Brückenanfragestruktur
typedef struct {
    uint32_t address;
    uint32_t data;
    uint8_t  security_id;
    bool     is_write;
} bridge_request_t;

void vulnerable_forward_request(bridge_request_t* req) {
    // VERWUNDBAR: Sicherheits-ID nicht korrekt konvertiert
    uint8_t proto_b_security = vulnerable_convert_security_id(req->security_id);

    // An Protokoll-B-Endpunkt weiterleiten
    send_proto_b_request(req->address, req->data, proto_b_security, req->is_write);
}

Sichere Lösung

// SICHER: AHB-zu-OCP-Brücke mit korrekter Sicherheits-ID-Konvertierung

module secure_ahb_to_ocp_bridge (
    input  wire        clk,
    input  wire        rst_n,

    // AHB-Signale
    input  wire [31:0] ahb_haddr,
    input  wire [2:0]  ahb_hburst,
    input  wire [3:0]  ahb_hprot,
    input  wire        ahb_hwrite,
    input  wire [31:0] ahb_hwdata,
    input  wire [1:0]  ahb_htrans,
    input  wire [3:0]  ahb_hmaster,    // AHB-Master-ID (implementierungsspezifisch)
    input  wire        ahb_hnonsec,    // AHB-Nicht-Sicher-Indikator

    // OCP-Signale
    output reg  [31:0] ocp_maddr,
    output reg  [2:0]  ocp_mburstlength,
    output reg  [1:0]  ocp_mcmd,
    output reg  [31:0] ocp_mdata,
    output reg  [7:0]  ocp_mtagid,
    output reg         ocp_mreqinfo
);

    // SICHER: Vollständige Sicherheitszuordnung mit allen relevanten Signalen
    reg [1:0] security_level;

    always @(*) begin
        // SICHER: Umfassende Sicherheitsstufenbestimmung
        if (!ahb_hnonsec) begin
            // Sicherer Zugriff
            if (ahb_hprot[1]) begin
                security_level = 2'b11;  // Sicher privilegiert
            end else begin
                security_level = 2'b10;  // Sicher Benutzer
            end
        end else begin
            // Nicht-sicherer Zugriff
            if (ahb_hprot[1]) begin
                security_level = 2'b01;  // Nicht-sicher privilegiert
            end else begin
                security_level = 2'b00;  // Nicht-sicher Benutzer (nicht vertrauenswürdig)
            end
        end
    end

    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            ocp_maddr <= 32'b0;
            ocp_mtagid <= 8'b0;
            ocp_mreqinfo <= 1'b0;
        end else begin
            ocp_maddr <= ahb_haddr;

            // SICHER: Ordnungsgemäße Sicherheitsstufenkonvertierung
            ocp_mtagid[7:6] <= security_level;

            // SICHER: Master-ID korrekt zugeordnet
            ocp_mtagid[5:2] <= ahb_hmaster;
            ocp_mtagid[1:0] <= 2'b00;  // Reserviert

            // SICHER: Sicherheitsinfo zeigt sicher/nicht-sicher korrekt an
            ocp_mreqinfo <= ahb_hnonsec;
        end
    end

    // SICHER: Assertions zur Verifizierung der Konvertierung
    // synthesis translate_off
    always @(posedge clk) begin
        if (!rst_n) begin
            // Reset
        end else begin
            // Verifizieren dass sicherer Zugriff korrekt abgebildet wird
            if (!ahb_hnonsec && ahb_hprot[1]) begin
                assert(ocp_mtagid[7:6] == 2'b11)
                    else $error("Sichere privilegierte Zuordnung fehlgeschlagen");
            end
        end
    end
    // synthesis translate_on

endmodule

// SICHER: APB-zu-AXI-Brücke mit korrekter Schutzbit-Zuordnung
module secure_apb_to_axi_bridge (
    input  wire        clk,
    input  wire        rst_n,

    // APB-Signale
    input  wire [31:0] paddr,
    input  wire        pwrite,
    input  wire [31:0] pwdata,
    input  wire        psel,
    input  wire        penable,
    input  wire [2:0]  pprot,

    // AXI-Signale
    output reg  [31:0] axi_awaddr,
    output reg  [2:0]  axi_awprot,
    output reg  [3:0]  axi_awcache,
    output reg  [31:0] axi_wdata,
    output reg         axi_awvalid
);

    // APB PPROT:
    // [0] = Normal(0)/Privilegiert(1)
    // [1] = Sicher(0)/Nicht-sicher(1)
    // [2] = Daten(0)/Instruktion(1)

    // AXI AWPROT:
    // [0] = Unprivilegiert(0)/Privilegiert(1)
    // [1] = Sicher(0)/Nicht-sicher(1)
    // [2] = Daten(0)/Instruktion(1)

    // SICHER: Explizite Bit-für-Bit-Zuordnung mit Dokumentation
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            axi_awprot <= 3'b000;  // Sicherer Standard: unprivilegiert, sicher, Daten
        end else begin
            // SICHER: Korrekte Zuordnung - Bits stimmen in diesem Fall zufällig überein
            // aber wir ordnen jedes einzeln zu für Klarheit und Wartbarkeit

            // Privileg-Bit: beide Protokolle verwenden gleiche Kodierung
            axi_awprot[0] <= pprot[0];

            // Sicherheits-Bit: beide Protokolle verwenden gleiche Kodierung (1=nicht-sicher)
            axi_awprot[1] <= pprot[1];

            // Daten/Instruktion-Bit: beide Protokolle verwenden gleiche Kodierung
            axi_awprot[2] <= pprot[2];
        end
    end

    // SICHER: Validierungslogik
    // synthesis translate_off
    always @(posedge clk) begin
        // Verifizieren dass privilegierter Zugriff erhalten bleibt
        if (pprot[0]) begin
            assert(axi_awprot[0]) else $error("Privileg nicht erhalten");
        end

        // Verifizieren dass sicher/nicht-sicher erhalten bleibt
        assert(axi_awprot[1] == pprot[1]) else $error("Sicherheit nicht erhalten");
    end
    // synthesis translate_on

endmodule
// SICHER: Software-Brücke mit korrekter Sicherheits-ID-Konvertierung

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

// Protokoll-A-Sicherheitsstufen
typedef enum {
    PROTO_A_UNTRUSTED  = 0x00,
    PROTO_A_USER       = 0x01,
    PROTO_A_SUPERVISOR = 0x02,
    PROTO_A_SECURE     = 0x03
} proto_a_security_t;

// Protokoll-B-Sicherheitsstufen (ändere Kodierung)
typedef enum {
    PROTO_B_PUBLIC     = 0x00,
    PROTO_B_NORMAL     = 0x04,
    PROTO_B_PRIVILEGED = 0x08,
    PROTO_B_HYPERVISOR = 0x0C
} proto_b_security_t;

// SICHER: Explizite Konvertierungstabelle
static const proto_b_security_t security_conversion_table[] = {
    [PROTO_A_UNTRUSTED]  = PROTO_B_PUBLIC,      // Niedrigste auf niedrigste abgebildet
    [PROTO_A_USER]       = PROTO_B_NORMAL,      // Benutzer auf normal abgebildet
    [PROTO_A_SUPERVISOR] = PROTO_B_PRIVILEGED,  // Supervisor auf privilegiert abgebildet
    [PROTO_A_SECURE]     = PROTO_B_HYPERVISOR   // Höchste auf höchste abgebildet
};

// SICHER: Validierte Konvertierungsfunktion
proto_b_security_t secure_convert_security_id(proto_a_security_t proto_a_id) {
    // SICHER: Eingabe validieren
    if (proto_a_id > PROTO_A_SECURE) {
        // Ungültige Eingabe - restriktivste Stufe zurückgeben
        log_security_error("Ungültige Protokoll-A-Sicherheits-ID: %d", proto_a_id);
        return PROTO_B_PUBLIC;  // Sicherer Standardwert
    }

    // SICHER: Explizite Zuordnungstabelle verwenden
    return security_conversion_table[proto_a_id];
}

// SICHER: Brücke mit validierter Konvertierung
typedef struct {
    uint32_t address;
    uint32_t data;
    proto_a_security_t security_id;
    bool is_write;
} bridge_request_t;

bool secure_forward_request(const bridge_request_t* req) {
    if (req == NULL) {
        return false;
    }

    // SICHER: Sicherheits-ID mit Validierung konvertieren
    proto_b_security_t proto_b_security = secure_convert_security_id(req->security_id);

    // SICHER: Konvertierung für Audit-Trail protokollieren
    audit_log("Sicherheitskonvertierung: ProtoA=%d -> ProtoB=%d",
              req->security_id, proto_b_security);

    // An Protokoll-B-Endpunkt weiterleiten
    return send_proto_b_request(req->address, req->data,
                                proto_b_security, req->is_write);
}

// SICHER: Umgekehrte Konvertierung für Antworten
proto_a_security_t secure_convert_security_id_reverse(proto_b_security_t proto_b_id) {
    switch (proto_b_id) {
        case PROTO_B_PUBLIC:     return PROTO_A_UNTRUSTED;
        case PROTO_B_NORMAL:     return PROTO_A_USER;
        case PROTO_B_PRIVILEGED: return PROTO_A_SUPERVISOR;
        case PROTO_B_HYPERVISOR: return PROTO_A_SECURE;
        default:
            log_security_error("Ungültige Protokoll-B-Sicherheits-ID: %d", proto_b_id);
            return PROTO_A_UNTRUSTED;  // Sicherer Standardwert
    }
}

// SICHER: Bidirektionale Brückenverifizierung
void verify_security_mapping(void) {
    // Round-Trip-Konvertierung erhält Sicherheitsstufe
    for (int i = PROTO_A_UNTRUSTED; i <= PROTO_A_SECURE; i++) {
        proto_b_security_t b = secure_convert_security_id(i);
        proto_a_security_t a_back = secure_convert_security_id_reverse(b);
        assert(a_back == i && "Sicherheitszuordnung ist nicht bijektiv!");
    }
}

CVE-Beispiele

  • CVE-2020-24512: Protokollbrücke in bestimmten Intel-Prozessoren ordnete Sicherheitsattribute bei Bus-Transaktionen falsch zu.
  • CVE-2019-11091: Fehler bei der Konvertierung von Sicherheitskennungen beim Microarchitectural Data Sampling.

Verwandte CWEs

  • CWE-284: Unsachgemäße Zugriffskontrolle (übergeordnet)
  • CWE-1294: Unsicherer Sicherheitskennungsmechanismus (übergeordnet)
  • CWE-1290: Fehlerhafte Dekodierung von Sicherheitskennungen (verwandt)
  • CWE-863: Fehlerhafte Autorisierung (verwandt)

Referenzen

  1. MITRE Corporation. "CWE-1292: Incorrect Conversion of Security Identifiers." https://cwe.mitre.org/data/definitions/1292.html
  2. ARM. "AMBA Protocol Specifications"
  3. OCP-IP. "Open Core Protocol Specification"