Richtlinienberechtigungen sind nicht konsistent zwischen Steuer- und Datenagenten zugewiesen

Beschreibung

Richtlinienberechtigungen sind nicht konsistent zwischen Steuer- und Datenagenten zugewiesen tritt auf, wenn hardwareerzwungene Zugriffskontrolle Berechtigungsdiskrepanzen zwischen Steuer- und Schreibrichtlinien, die den Ressourcenzugriff betreffen, nicht ordnungsgemäß berucksichtigt. Hardwaresysteme implementieren oft mehrstufige Zugriffsrichtlinien zur Steuerung des Ressourcenzugriffs, einschließlich Konfigurations- und Verschlüsselungsschlüssel. Wenn Steuerrichtlinien sowohl direkten Ressourcenzugriff als auch Richtlinienänderungen erlauben, entstehen Schwachstellen bei Ressourcen, die in Steuerrichtlinien enthalten, aber aus Schreibrichtlinien ausgeschlossen sind. Ein nicht vertrauenswurdiger Agent könnte diese Lucke ausnutzen, um sich selbst in Schreibrichtlinienregister einzufugen und möglicherweise unbefugten Schreibzugriff zu erlangen.

Risiko

Inkonsistente Richtlinienberechtigungen haben schwerwiegende Sicherheitsauswirkungen. Nicht vertrauenswurdige Agenten können sich selbst Zugriff gewahren. Schreibrichtlinien können über Steuerzugriff modifiziert werden. Sicherheitskonfigurationen können kompromittiert werden. Verschlüsselungsschlüssel können uberschrieben werden. Berechtigungserweiterung wird möglich. Schutzmechanismen können umgangen werden. Systemsicherheit kann untergraben werden. Zugriffskontrolle wird unwirksam.

Lösung

Zugriffskontrollrichtlinien erfordern umfassende Tests sowohl in Pre-Silicon- als auch in Post-Silicon-Entwicklungsphasen, um konsistente Berechtigungszuweisung über alle Richtlinienebenen sicherzustellen. Stellen Sie sicher, dass Agenten mit Steuerzugriff auf eine Ressource auch konsistente Datenzugriffsberechtigungen haben. Implementieren Sie Berechtigungstrennung zwischen Richtlinienänderung und Ressourcenzugriff. Uberprüfen Sie Richtlinienkonsistenz während Sicherheitsreviews.

Häufige Auswirkungen

AuswirkungDetails
VertraulichkeitUmfang: Vertraulichkeit

Speicher lesen - Inkonsistente Richtlinien können unbefugten Datenzugriff ermöglichen.
IntegritatUmfang: Integritat

Speicher modifizieren - Agenten können Schreibzugriff durch Richtlinienmanipulation erlangen.
ZugriffskontrolleUmfang: Zugriffskontrolle

Schutzmechanismus umgehen - Richtlinieninkonsistenzen ermöglichen Berechtigungserweiterung.

Beispielcode und Lösung

Verwundbarer Code

// VERWUNDBAR: Inkonsistente Steuer- und Datenrichtlinien

module vulnerable_aes_policy (
    input wire clk,
    input wire reset_n,
    // Agenten-Schnittstelle
    input wire [3:0] agent_id,
    input wire [7:0] reg_addr,
    input wire [31:0] reg_write_data,
    input wire reg_write,
    input wire reg_read,
    output reg [31:0] reg_read_data,
    output reg access_denied
);

    // AES-Schlüsselspeicher
    reg [127:0] aes_key;

    // Richtlinienregister
    reg [15:0] aes_key_control_policy;  // Wer kann Richtlinien ändern
    reg [15:0] aes_key_read_policy;     // Wer kann Schlüssel lesen
    reg [15:0] aes_key_write_policy;    // Wer kann Schlüssel schreiben

    // Registeradressen
    parameter AES_KEY_REG = 8'h00;
    parameter CONTROL_POLICY_REG = 8'h10;
    parameter READ_POLICY_REG = 8'h14;
    parameter WRITE_POLICY_REG = 8'h18;

    // VERWUNDBAR: Initiale Richtlinienzuweisung
    initial begin
        // Agent 0: Secure Master - voller Zugriff
        // Agent 1: Crypto Engine - Schlüssel lesen/schreiben
        // Agent 2: Boot ROM - nur Schlüssel lesen
        // Agent 3: Nicht vertrauenswurdiger Debug - SOLLTE keinen Zugriff haben

        aes_key_control_policy = 16'b0000_0000_0000_1111;
        // Agenten 0,1,2,3 können Richtlinien ändern
        // VERWUNDBAR: Agent 3 (nicht vertrauenswurdig) hat Steuerzugriff!

        aes_key_read_policy = 16'b0000_0000_0000_0111;
        // Agenten 0,1,2 können Schlüssel lesen

        aes_key_write_policy = 16'b0000_0000_0000_0011;
        // Agenten 0,1 können Schlüssel schreiben
        // Agent 3 kann Schlüssel nicht direkt schreiben
    end

    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            access_denied <= 1'b0;
        end
        else if (reg_write) begin
            access_denied <= 1'b0;

            case (reg_addr)
                AES_KEY_REG: begin
                    // Schreibrichtlinie prüfen
                    if (aes_key_write_policy[agent_id]) begin
                        aes_key <= reg_write_data;
                    end
                    else begin
                        access_denied <= 1'b1;
                    end
                end

                WRITE_POLICY_REG: begin
                    // VERWUNDBAR: Steuerrichtlinie für Richtlinienänderung prüfen
                    if (aes_key_control_policy[agent_id]) begin
                        // Agent 3 kann hierher gelangen!
                        // Agent 3 setzt Bit 3 um sich selbst Schreibzugriff zu geben
                        aes_key_write_policy <= reg_write_data;
                    end
                    else begin
                        access_denied <= 1'b1;
                    end
                end

                // Ähnliche Schwachstelle für andere Richtlinienregister
            endcase
        end
    end

    // Angriff durch Agent 3:
    // 1. Agent 3 hat Steuerrichtlinien-Zugriff (Bit 3 gesetzt)
    // 2. Agent 3 schreibt in WRITE_POLICY_REG
    // 3. Agent 3 setzt Bit 3 in Schreibrichtlinie
    // 4. Jetzt hat Agent 3 Schreibzugriff auf den AES-Schlüssel!

endmodule
// VERWUNDBAR: Software-Richtlinie mit inkonsistenten Berechtigungen

#include <stdint.h>

typedef struct {
    uint32_t control_mask;   // Wer kann Richtlinien ändern
    uint32_t read_mask;      // Wer kann Ressource lesen
    uint32_t write_mask;     // Wer kann Ressource schreiben
} resource_policy_t;

// VERWUNDBAR: Inkonsistente Richtlinienzuweisung
resource_policy_t secret_key_policy = {
    .control_mask = 0x0000000F,  // Agenten 0-3 können Richtlinien ändern
    .read_mask    = 0x00000007,  // Agenten 0-2 können lesen
    .write_mask   = 0x00000003,  // Agenten 0-1 können schreiben
    // Agent 3 hat Steuer- aber nicht Lese-/Schreibzugriff
    // Diese Inkonsistenz ist ausnutzbar
};

int vulnerable_modify_policy(uint32_t agent_id, resource_policy_t* policy,
                             uint32_t policy_type, uint32_t new_value) {
    // Prüfen ob Agent Steuerzugriff hat
    if (!(policy->control_mask & (1 << agent_id))) {
        return -EACCES;
    }

    // VERWUNDBAR: Agent mit Steuerzugriff kann jede Richtlinie ändern
    switch (policy_type) {
        case POLICY_CONTROL:
            policy->control_mask = new_value;
            break;
        case POLICY_READ:
            policy->read_mask = new_value;
            break;
        case POLICY_WRITE:
            // Agent 3 kann dies setzen um sich selbst Schreibzugriff zu geben!
            policy->write_mask = new_value;
            break;
    }

    return 0;
}

// Angriff:
// 1. Agent 3 ruft vulnerable_modify_policy(..., POLICY_WRITE, 0x0000000F) auf
// 2. Jetzt hat Agent 3 Schreibzugriff auf den geheimen Schlüssel

Sichere Lösung

// SICHER: Konsistente Richtlinienberechtigungen

module secure_aes_policy (
    input wire clk,
    input wire reset_n,
    input wire [3:0] agent_id,
    input wire [7:0] reg_addr,
    input wire [31:0] reg_write_data,
    input wire reg_write,
    input wire reg_read,
    output reg [31:0] reg_read_data,
    output reg access_denied,
    output reg policy_violation
);

    // AES-Schlüsselspeicher
    reg [127:0] aes_key;

    // Richtlinienregister
    reg [15:0] aes_key_control_policy;
    reg [15:0] aes_key_read_policy;
    reg [15:0] aes_key_write_policy;

    // SICHER: Master-Richtlinie - nur Secure Master kann ändern
    parameter SECURE_MASTER = 4'd0;

    // Registeradressen
    parameter AES_KEY_REG = 8'h00;
    parameter CONTROL_POLICY_REG = 8'h10;
    parameter READ_POLICY_REG = 8'h14;
    parameter WRITE_POLICY_REG = 8'h18;

    // SICHER: Konsistente Richtlinienzuweisung
    initial begin
        // Nur vertrauenswurdige Agenten haben Steuerzugriff
        aes_key_control_policy = 16'b0000_0000_0000_0001;
        // Nur Agent 0 (Secure Master) kann Richtlinien ändern

        aes_key_read_policy = 16'b0000_0000_0000_0111;
        // Agenten 0,1,2 können Schlüssel lesen

        aes_key_write_policy = 16'b0000_0000_0000_0011;
        // Agenten 0,1 können Schlüssel schreiben
    end

    // SICHER: Richtlinienkonsistenz validieren
    function automatic is_policy_consistent;
        input [15:0] new_control;
        input [15:0] current_read;
        input [15:0] current_write;
        begin
            // Steuerrichtlinie muss Teilmenge von Lese- UND Schreibrichtlinie sein
            // Oder: Agenten mit Steuerzugriff müssen auch Datenzugriff haben
            is_policy_consistent =
                ((new_control & ~current_read) == 16'h0) &&
                ((new_control & ~current_write) == 16'h0);
        end
    endfunction

    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            access_denied <= 1'b0;
            policy_violation <= 1'b0;
        end
        else if (reg_write) begin
            access_denied <= 1'b0;
            policy_violation <= 1'b0;

            case (reg_addr)
                AES_KEY_REG: begin
                    if (aes_key_write_policy[agent_id]) begin
                        aes_key <= reg_write_data;
                    end
                    else begin
                        access_denied <= 1'b1;
                    end
                end

                CONTROL_POLICY_REG: begin
                    // SICHER: Nur Secure Master kann Steuerrichtlinie ändern
                    if (agent_id == SECURE_MASTER) begin
                        // SICHER: Neue Richtlinie auf Konsistenz validieren
                        if (is_policy_consistent(reg_write_data,
                                                 aes_key_read_policy,
                                                 aes_key_write_policy)) begin
                            aes_key_control_policy <= reg_write_data;
                        end
                        else begin
                            policy_violation <= 1'b1;
                        end
                    end
                    else begin
                        access_denied <= 1'b1;
                    end
                end

                WRITE_POLICY_REG: begin
                    // SICHER: Nur Secure Master kann Schreibrichtlinie ändern
                    if (agent_id == SECURE_MASTER) begin
                        aes_key_write_policy <= reg_write_data;
                    end
                    else begin
                        access_denied <= 1'b1;
                    end
                end

                READ_POLICY_REG: begin
                    // SICHER: Nur Secure Master kann Leserichtlinie ändern
                    if (agent_id == SECURE_MASTER) begin
                        aes_key_read_policy <= reg_write_data;
                    end
                    else begin
                        access_denied <= 1'b1;
                    end
                end
            endcase
        end
    end

endmodule

// Alternative: Hierarchische Richtlinie mit Berechtigungsstufen
module secure_hierarchical_policy (
    input wire clk,
    input wire reset_n,
    input wire [3:0] agent_id,
    input wire [1:0] agent_privilege,  // 0=Benutzer, 1=Supervisor, 2=Hypervisor, 3=Sicher
    input wire [7:0] reg_addr,
    input wire [31:0] reg_write_data,
    input wire reg_write,
    output reg access_denied
);

    // SICHER: Erforderliche Berechtigung für jede Operation
    parameter CONTROL_PRIV = 2'd3;  // Nur Sicher
    parameter WRITE_PRIV = 2'd2;    // Hypervisor+
    parameter READ_PRIV = 2'd1;     // Supervisor+

    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            access_denied <= 1'b0;
        end
        else if (reg_write) begin
            case (reg_addr)
                POLICY_REG: begin
                    // SICHER: Nur höchste Berechtigung kann Richtlinien ändern
                    if (agent_privilege >= CONTROL_PRIV) begin
                        // Richtlinie aktualisieren
                    end
                    else begin
                        access_denied <= 1'b1;
                    end
                end

                DATA_REG: begin
                    // SICHER: Schreiben erfordert entsprechende Berechtigung
                    if (agent_privilege >= WRITE_PRIV) begin
                        // Daten schreiben
                    end
                    else begin
                        access_denied <= 1'b1;
                    end
                end
            endcase
        end
    end

endmodule
// SICHER: Software-Richtlinie mit konsistenten Berechtigungen

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

typedef struct {
    uint32_t control_mask;
    uint32_t read_mask;
    uint32_t write_mask;
    bool locked;  // SICHER: Richtlinie kann gesperrt werden
} resource_policy_t;

// SICHER: Richtlinienkonsistenz validieren
static bool is_policy_consistent(const resource_policy_t* policy,
                                 uint32_t new_control) {
    // Steueragenten müssen entsprechenden Datenzugriff haben
    // um Berechtigungserweiterung zu verhindern

    // Jeder Agent mit Steuerzugriff muss Lesezugriff haben
    if ((new_control & ~policy->read_mask) != 0) {
        return false;
    }

    // Jeder Agent mit Steuerzugriff muss Schreibzugriff haben
    // (oder Steuerung darf nur für Lese-Richtlinien gelten)
    if ((new_control & ~policy->write_mask) != 0) {
        return false;
    }

    return true;
}

// SICHER: Sichere Richtlinienänderung
int secure_modify_policy(uint32_t agent_id, uint32_t agent_privilege,
                         resource_policy_t* policy,
                         uint32_t policy_type, uint32_t new_value) {
    // SICHER: Richtlinienänderung erfordert höchste Berechtigung
    if (agent_privilege < PRIVILEGE_SECURE) {
        log_access_denied("Richtlinienänderung erfordert sichere Berechtigung");
        return -EPERM;
    }

    // SICHER: Prüfen ob Richtlinie gesperrt ist
    if (policy->locked) {
        log_access_denied("Richtlinie ist gesperrt");
        return -EPERM;
    }

    switch (policy_type) {
        case POLICY_CONTROL:
            // SICHER: Konsistenz vor Anwendung validieren
            if (!is_policy_consistent(policy, new_value)) {
                log_error("Inkonsistente Steuerrichtlinie abgelehnt");
                return -EINVAL;
            }
            policy->control_mask = new_value;
            break;

        case POLICY_READ:
            // SICHER: Sicherstellen dass Steuer-Teilmenge von Lese ist
            if ((policy->control_mask & ~new_value) != 0) {
                log_error("Leserichtlinie würde Steueragenten ausschließen");
                return -EINVAL;
            }
            policy->read_mask = new_value;
            break;

        case POLICY_WRITE:
            // SICHER: Sicherstellen dass Steuer-Teilmenge von Schreib ist
            if ((policy->control_mask & ~new_value) != 0) {
                log_error("Schreibrichtlinie würde Steueragenten ausschließen");
                return -EINVAL;
            }
            policy->write_mask = new_value;
            break;

        case POLICY_LOCK:
            // SICHER: Richtliniensperrung erlauben
            policy->locked = true;
            break;

        default:
            return -EINVAL;
    }

    log_policy_change(agent_id, policy_type, new_value);
    return 0;
}

// SICHER: Factory-Funktion für konsistente Richtlinien
resource_policy_t create_consistent_policy(uint32_t trusted_agents,
                                           uint32_t read_agents,
                                           uint32_t write_agents) {
    resource_policy_t policy;

    // Konsistenz bei Erstellung sicherstellen
    // Vertrauenswürdige Agenten müssen Teilmenge von Lese und Schreib sein
    policy.read_mask = read_agents | trusted_agents;
    policy.write_mask = write_agents | trusted_agents;
    policy.control_mask = trusted_agents;  // Nur Vertrauenswürdige können ändern
    policy.locked = false;

    return policy;
}

CVE-Beispiele

Schwachstellen durch inkonsistente Richtlinien wurden in SoC-Designs gefunden, bei denen nicht vertrauenswurdige Agenten Steuerzugriff ausnutzen könnten, um sich selbst Datenzugriffsberechtigungen zu gewahren, die sie nicht haben sollten.


Verwandte CWEs

  • CWE-266: Fehlerhafte Berechtigungszuweisung (ubergeordnet)
  • CWE-1267: Richtlinie verwendet veraltete Kodierung (verwandt)
  • CWE-1259: Unsachgemäße Einschränkung der Sicherheitstoken-Zuweisung (verwandt)
  • CAPEC-180: Ausnutzung fehlerhaft konfigurierter Zugriffskontrollebenen (Angriffsmuster)

Referenzen

  1. MITRE Corporation. "CWE-1268: Policy Privileges are not Assigned Consistently Between Control and Data Agents." https://cwe.mitre.org/data/definitions/1268.html
  2. ARM. "TrustZone Security Extensions"
  3. RISC-V. "Physical Memory Protection Specification"