Unsachgemäße Einschränkung der Sicherheitstoken-Zuweisung

Beschreibung

Unsachgemäße Einschränkung der Sicherheitstoken-Zuweisung tritt auf, wenn Systems-on-Chip Sicherheitstoken verwenden, um zu unterscheiden, welche Aktionen von verschiedenen Entitäten erlaubt sind, diese Token jedoch unzureichend geschützt sind. Sicherheitstoken identifizieren, welcher Agent eine Aktion initiiert hat (Lesen, Schreiben, Programmieren, Zurücksetzen, Abrufen, Berechnen usw.) und definieren deren Vertrauensstufe und Berechtigungen. Die Schwachstelle resultiert aus der unsachgemäßen Einschränkung der Zuweisung auf vertrauenswürdige Komponenten, wodurch bösartige Agenten ihre Token ändern und sich als legitime Entitäten ausgeben können.

Risiko

Unsachgemäßer Token-Schutz hat schwerwiegende Sicherheitsauswirkungen. Bösartige Agenten können vertrauenswürdige Transaktionen fälschen. Privilegieneskalation wird möglich. Zugriffskontrolle kann umgangen werden. Unautorisierter Code kann ausgeführt werden. Speicher kann ohne Autorisierung modifiziert werden. Systemsicherheitsgrenzen werden verletzt. Angreifer können jede Identität annehmen. Denial-of-Service-Angriffe werden möglich.

Lösung

Führen Sie Überprüfungen der Sicherheitstoken-Zuweisung auf Design-Inkonsistenzen durch. Testen Sie Token-Definitions- und Programmierflüsse in Pre-Silicon- und Post-Silicon-Umgebungen. Verhindern Sie, dass ein Agent Sicherheitstoken modifizieren kann, außer durch sichere Hardware-Mechanismen. Verwenden Sie hardware-erzwungene Token-Zuweisung. Implementieren Sie Token-Integritätsprüfung. Machen Sie Token nach der Zuweisung unveränderlich. Verwenden Sie kryptographischen Schutz für Token-Werte.

Häufige Auswirkungen

AuswirkungDetails
AutorisierungBereich: Autorisierung

Privilegieneskalation - Bösartige Agenten können Token modifizieren, um höhere Privilegien zu erlangen.
ZugriffskontrolleBereich: Zugriffskontrolle

Umgehung des Schutzmechanismus - Token-Spoofing ermöglicht die Umgehung von Zugriffskontrollprüfungen.
IntegritätBereich: Integrität

Speicher modifizieren - Unautorisierte Speichermodifikation durch gefälschte Transaktionen.

Beispielcode und Lösung

Verwundbarer Code

// VERWUNDBAR: Veränderbare Sicherheitstoken

module vulnerable_token_system (
    input wire clk,
    input wire reset_n,
    input wire [3:0] agent_id,
    input wire [3:0] token_write_data,
    input wire token_write_enable,
    input wire [31:0] bus_addr,
    input wire [31:0] bus_data,
    input wire bus_write,
    input wire bus_read,
    output reg [31:0] bus_read_data,
    output reg access_granted
);

    // Sicherheitstoken-Speicher für jeden Agenten
    reg [3:0] agent_tokens [0:15];

    // Sicherheitsstufen: 0=nicht vertrauenswürdig, 1=Benutzer, 2=Supervisor, 3=sicher
    parameter SECURE_REGION_START = 32'h8000_0000;
    parameter SECURE_REGION_END = 32'h8FFF_FFFF;
    parameter REQUIRED_TOKEN = 4'd3;  // Sichere Stufe erforderlich

    // VERWUNDBAR: Jeder Agent kann jeden Token modifizieren
    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            // Initialisiert alle Agenten mit niedrigen Privilegien
            integer i;
            for (i = 0; i < 16; i = i + 1) begin
                agent_tokens[i] <= 4'd0;  // Nicht vertrauenswürdig
            end
        end
        else if (token_write_enable) begin
            // VERWUNDBAR: Keine Prüfung, wer das Token schreibt
            // Jeder Agent kann seine eigenen oder fremde Token erhöhen
            agent_tokens[agent_id] <= token_write_data;
        end
    end

    // Zugriffskontrolle mit Token
    wire is_secure_region = (bus_addr >= SECURE_REGION_START) &&
                            (bus_addr <= SECURE_REGION_END);
    wire agent_token = agent_tokens[agent_id];

    always @(*) begin
        if (is_secure_region) begin
            // Prüft das Token des Agenten
            access_granted = (agent_token >= REQUIRED_TOKEN);
        end
        else begin
            access_granted = 1'b1;
        end
    end

    // Angriffsszenario:
    // 1. Bösartiger Agent hat Token 0 (nicht vertrauenswürdig)
    // 2. Agent schreibt token_write_data=3, token_write_enable=1
    // 3. Agent hat jetzt Token 3 (sicher) - kann auf sicheren Bereich zugreifen

endmodule

// VERWUNDBAR: Token kann über Registerschnittstelle modifiziert werden
module vulnerable_aux_controller (
    input wire clk,
    input wire reset_n,
    input wire [7:0] reg_addr,
    input wire [31:0] reg_write_data,
    input wire reg_write,
    output reg [3:0] my_token,
    output reg [31:0] reg_read_data
);

    // Interne Register
    reg [31:0] config_reg;
    reg [31:0] status_reg;

    // Token-Speicherregister
    reg [3:0] token_reg;

    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            token_reg <= 4'd2;  // Initialisiert als Benutzerstufe
            config_reg <= 32'h0;
            status_reg <= 32'h0;
        end
        else if (reg_write) begin
            case (reg_addr)
                8'h00: config_reg <= reg_write_data;
                8'h04: status_reg <= reg_write_data;
                // VERWUNDBAR: Token kann geschrieben werden!
                8'h08: token_reg <= reg_write_data[3:0];
                default: ;
            endcase
        end
    end

    assign my_token = token_reg;

    // Angriff: Schreibe an reg_addr 0x08, um Token-Wert zu ändern

endmodule
// VERWUNDBAR: Software-Token-Modifikation

#include <stdint.h>

#define TOKEN_REGISTER_BASE 0x10000000
#define MAX_AGENTS 16

typedef struct {
    uint32_t token;
    uint32_t permissions;
    uint32_t reserved[2];
} agent_token_t;

volatile agent_token_t* token_table = (volatile agent_token_t*)TOKEN_REGISTER_BASE;

// VERWUNDBAR: Jeder Code kann dies aufrufen, um Token zu modifizieren
void vulnerable_set_token(int agent_id, uint32_t new_token) {
    if (agent_id < MAX_AGENTS) {
        // VERWUNDBAR: Keine Privilegienprüfung
        // Jeder Agent kann jeden Token modifizieren
        token_table[agent_id].token = new_token;
    }
}

// VERWUNDBAR: Token-Prüfung kann umgangen werden
int vulnerable_check_access(int agent_id, uint32_t resource_id) {
    // Token des Agenten lesen
    uint32_t token = token_table[agent_id].token;

    // VERWUNDBAR: Token wurde bereits vom Angreifer modifiziert
    if (token >= REQUIRED_TOKEN_LEVEL) {
        return ACCESS_GRANTED;
    }
    return ACCESS_DENIED;
}

// Angriff:
// 1. Angreifer ist Agent 5 mit Token 0
// 2. Angreifer ruft vulnerable_set_token(5, HIGHEST_TOKEN) auf
// 3. Angreifer besteht jetzt alle Token-Prüfungen

Sichere Lösung

// SICHER: Unveränderliche Sicherheitstoken mit Hardware-Durchsetzung

module secure_token_system (
    input wire clk,
    input wire reset_n,
    input wire [3:0] agent_id,
    input wire [3:0] token_write_data,
    input wire token_write_enable,
    input wire secure_master,          // Nur wahr für sicheren Master
    input wire token_program_mode,     // Einmaliger Programmiermodus
    input wire [31:0] bus_addr,
    input wire [31:0] bus_data,
    input wire bus_write,
    input wire bus_read,
    output reg [31:0] bus_read_data,
    output reg access_granted,
    output reg token_violation
);

    // Sicherheitstoken-Speicher
    reg [3:0] agent_tokens [0:15];
    reg token_locked [0:15];  // Sperr-Flag für jedes Token

    // Parameter
    parameter SECURE_REGION_START = 32'h8000_0000;
    parameter SECURE_REGION_END = 32'h8FFF_FFFF;
    parameter REQUIRED_TOKEN = 4'd3;

    // SICHER: Token-Modifikation mit strengen Kontrollen
    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            integer i;
            for (i = 0; i < 16; i = i + 1) begin
                agent_tokens[i] <= 4'd0;
                token_locked[i] <= 1'b0;
            end
            token_violation <= 1'b0;
        end
        else if (token_write_enable) begin
            // SICHER: Mehrere Prüfungen für Token-Modifikation erforderlich
            if (!secure_master) begin
                // SICHER: Nur sicherer Master kann Token modifizieren
                token_violation <= 1'b1;
            end
            else if (!token_program_mode) begin
                // SICHER: Muss im Programmiermodus sein
                token_violation <= 1'b1;
            end
            else if (token_locked[agent_id]) begin
                // SICHER: Gesperrte Token können nicht modifiziert werden
                token_violation <= 1'b1;
            end
            else begin
                // SICHER: Legitime Token-Zuweisung
                agent_tokens[agent_id] <= token_write_data;
                // SICHER: Token nach Zuweisung sperren
                token_locked[agent_id] <= 1'b1;
            end
        end
    end

    // Zugriffskontrolle
    wire is_secure_region = (bus_addr >= SECURE_REGION_START) &&
                            (bus_addr <= SECURE_REGION_END);

    always @(*) begin
        if (is_secure_region) begin
            // SICHER: Hardware-kontrolliertes Token verwenden
            access_granted = (agent_tokens[agent_id] >= REQUIRED_TOKEN);
        end
        else begin
            access_granted = 1'b1;
        end
    end

endmodule

// SICHER: Hardware-erzwungenes unveränderliches Token
module secure_aux_controller (
    input wire clk,
    input wire reset_n,
    input wire [7:0] reg_addr,
    input wire [31:0] reg_write_data,
    input wire reg_write,
    input wire fuse_token_valid,       // Fuse-basiertes Token
    input wire [3:0] fuse_token_value, // Unveränderlich aus Fuses
    output wire [3:0] my_token,
    output reg [31:0] reg_read_data,
    output reg token_tamper_attempt
);

    // Interne Register
    reg [31:0] config_reg;
    reg [31:0] status_reg;

    // SICHER: Token kommt von Hardware-Fuses, nicht von Software
    assign my_token = fuse_token_valid ? fuse_token_value : 4'd0;

    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            config_reg <= 32'h0;
            status_reg <= 32'h0;
            token_tamper_attempt <= 1'b0;
        end
        else if (reg_write) begin
            case (reg_addr)
                8'h00: config_reg <= reg_write_data;
                8'h04: status_reg <= reg_write_data;
                // SICHER: Token-Register ist schreibgeschützt
                8'h08: begin
                    // Versuch, Token zu schreiben - als Manipulation markieren
                    token_tamper_attempt <= 1'b1;
                    // Wert wird NICHT modifiziert
                end
                default: ;
            endcase
        end
    end

    // Leseschnittstelle
    always @(*) begin
        case (reg_addr)
            8'h00: reg_read_data = config_reg;
            8'h04: reg_read_data = status_reg;
            8'h08: reg_read_data = {28'h0, my_token};  // Nur lesen
            default: reg_read_data = 32'h0;
        endcase
    end

endmodule

// SICHER: Transaktionsebene-Token-Verifizierung
module secure_bus_firewall (
    input wire clk,
    input wire reset_n,
    input wire [3:0] requester_id,
    input wire [31:0] transaction_addr,
    input wire [3:0] claimed_token,    // Vom Anforderer beanspruchtes Token
    input wire transaction_valid,
    output reg transaction_allowed,
    output reg token_mismatch
);

    // SICHER: Hardware-Token-Tabelle (schreibgeschützt für Anforderer)
    reg [3:0] authentic_tokens [0:15];

    // SICHER: Beanspruchtes Token mit authentischem Token vergleichen
    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            transaction_allowed <= 1'b0;
            token_mismatch <= 1'b0;
        end
        else if (transaction_valid) begin
            // SICHER: Überprüfen, ob beanspruchtes Token mit authentischem Token übereinstimmt
            if (claimed_token != authentic_tokens[requester_id]) begin
                // Token-Spoofing erkannt!
                token_mismatch <= 1'b1;
                transaction_allowed <= 1'b0;
            end
            else begin
                token_mismatch <= 1'b0;
                // Zugriff basierend auf authentischem Token prüfen
                transaction_allowed <= check_access(transaction_addr, authentic_tokens[requester_id]);
            end
        end
    end

endmodule
// SICHER: Sichere Token-Verwaltung

#include <stdint.h>

#define TOKEN_REGISTER_BASE 0x10000000
#define MAX_AGENTS 16

// SICHER: Token-Tabelle ist im sicheren Speicher, nicht direkt zugänglich
typedef struct {
    uint32_t token;
    uint32_t permissions;
    uint32_t locked;  // Einmal gesetzt, kann Token nicht mehr geändert werden
    uint32_t checksum;
} secure_agent_token_t;

// SICHER: Hardware-verwaltete Token-Abfrage
static uint32_t get_authentic_token(int agent_id) {
    // Diese Funktion läuft nur im sicheren Modus
    // Token wird von Hardware abgerufen, nicht aus Speicher
    return SECURE_TOKEN_HARDWARE->agent_token[agent_id];
}

// SICHER: Token-Zuweisung nur während sicherem Boot
int secure_set_token(int agent_id, uint32_t new_token) {
    // SICHER: Prüfen, ob wir im sicheren Programmiermodus sind
    if (!is_secure_boot_mode()) {
        log_security_violation("Token-Modifikation außerhalb des Boots");
        return -EPERM;
    }

    // SICHER: Prüfen, ob Aufrufer sicherer Master ist
    if (get_current_privilege() < PRIVILEGE_SECURE_MASTER) {
        log_security_violation("Unprivilegierte Token-Modifikation");
        return -EPERM;
    }

    // SICHER: Prüfen, ob Token bereits gesperrt ist
    if (SECURE_TOKEN_HARDWARE->agent_locked[agent_id]) {
        log_security_violation("Versuch, gesperrtes Token zu modifizieren");
        return -EPERM;
    }

    // SICHER: Token über sichere Hardware-Schnittstelle programmieren
    SECURE_TOKEN_HARDWARE->agent_token[agent_id] = new_token;

    // SICHER: Token sperren, um zukünftige Modifikation zu verhindern
    SECURE_TOKEN_HARDWARE->agent_locked[agent_id] = 1;

    // Programmierung verifizieren
    if (SECURE_TOKEN_HARDWARE->agent_token[agent_id] != new_token) {
        return -EIO;
    }

    return 0;
}

// SICHER: Zugriffsprüfung verwendet Hardware-Token
int secure_check_access(int agent_id, uint32_t resource_id) {
    // SICHER: Token von Hardware holen, nicht vom Agenten
    uint32_t authentic_token = get_authentic_token(agent_id);

    // SICHER: Auch Token-Integrität verifizieren
    if (!verify_token_integrity(agent_id)) {
        log_security_violation("Token-Integritätsfehler");
        return ACCESS_DENIED;
    }

    if (authentic_token >= get_required_token(resource_id)) {
        return ACCESS_GRANTED;
    }

    return ACCESS_DENIED;
}

// SICHER: Verifizieren, dass Token nicht manipuliert wurde
static bool verify_token_integrity(int agent_id) {
    uint32_t stored_checksum = SECURE_TOKEN_HARDWARE->agent_checksum[agent_id];
    uint32_t computed_checksum = compute_token_checksum(
        SECURE_TOKEN_HARDWARE->agent_token[agent_id],
        agent_id
    );

    return (stored_checksum == computed_checksum);
}

CVE-Beispiele

Sicherheitstoken-Schwachstellen wurden in verschiedenen SoC-Designs gefunden, bei denen Hilfscontroller ihre Sicherheitskennungen modifizieren könnten, um unautorisierten Zugriff auf geschützte Ressourcen wie Verschlüsselungsschlüssel zu erlangen.


Verwandte CWEs

  • CWE-284: Unsachgemäße Zugriffskontrolle (Eltern)
  • CWE-1294: Unsicherer Sicherheitskennungsmechanismus (Eltern)
  • CWE-1255: Vergleichslogik ist anfällig für Power-Seitenkanalangriffe (Peer)
  • CWE-1270: Generierung falscher Sicherheitstoken (verwandt)

Referenzen

  1. MITRE Corporation. "CWE-1259: Improper Restriction of Security Token Assignment." https://cwe.mitre.org/data/definitions/1259.html
  2. ARM. "TrustZone Security" - Security Identifiers
  3. AMBA. "AXI Protocol" - Transaction Security