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
| Auswirkung | Details |
|---|---|
| Vertraulichkeit | Umfang: Vertraulichkeit Speicher lesen - Inkonsistente Richtlinien können unbefugten Datenzugriff ermöglichen. |
| Integritat | Umfang: Integritat Speicher modifizieren - Agenten können Schreibzugriff durch Richtlinienmanipulation erlangen. |
| Zugriffskontrolle | Umfang: 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
- MITRE Corporation. "CWE-1268: Policy Privileges are not Assigned Consistently Between Control and Data Agents." https://cwe.mitre.org/data/definitions/1268.html
- ARM. "TrustZone Security Extensions"
- RISC-V. "Physical Memory Protection Specification"