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
| Auswirkung | Details |
|---|---|
| Autorisierung | Bereich: Autorisierung Privilegieneskalation - Bösartige Agenten können Token modifizieren, um höhere Privilegien zu erlangen. |
| Zugriffskontrolle | Bereich: Zugriffskontrolle Umgehung des Schutzmechanismus - Token-Spoofing ermöglicht die Umgehung von Zugriffskontrollprüfungen. |
| Integrität | Bereich: 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
- MITRE Corporation. "CWE-1259: Improper Restriction of Security Token Assignment." https://cwe.mitre.org/data/definitions/1259.html
- ARM. "TrustZone Security" - Security Identifiers
- AMBA. "AXI Protocol" - Transaction Security