Fehlerhafte Dekodierung von Sicherheitskennungen
Beschreibung
Fehlerhafte Dekodierung von Sicherheitskennungen tritt auf, wenn ein Produkt einen Dekodierungsmechanismus implementiert, der Bus-Transaktionssignale falsch zu Sicherheitskennungen dekodiert. In System-on-Chip (SoC)-Umgebungen enthalten Hardware-Transaktionen typischerweise Quell- und Zielidentitäten zusammen mit Sicherheitskennungen, die bestimmen, welche Agenten Zugriff auf Assets erhalten und welche Aktionen sie ausführen können. Wenn der Dekodierer die Sicherheitskennung eines nicht vertrauenswürdigen Agenten fälschlicherweise einer vertrauenswürdigen zuordnet, gewährt er versehentlich unbefugten Zugriff auf geschützte Ressourcen.
Risiko
Fehlerhafte Dekodierung von Sicherheitskennungen hat schwerwiegende Auswirkungen. Nicht vertrauenswürdige Agenten erhalten unbefugten Zugriff. Speichermodifikation möglich. Unbefugte Lesezugriffe aktiviert. Denial of Service durch Ressourcenverbrauch. Ausführung von unbefugtem Code. Privilegieneskalation möglich. Identitätsübernahme-Angriffe ermöglicht. Vollständige Umgehung von Zugriffskontrollen. Hohe Ausnutzungswahrscheinlichkeit sobald der Fehler existiert.
Lösung
Dekodierer für Sicherheitskennungen erfordern eine Überprüfung auf Designkonsistenz und Identifikation häufiger Schwachstellen während der Architektur- und Entwurfsphase. Stellen Sie eine vollständige Bitfeld-Prüfung statt partieller Prüfungen sicher. Zugriffs- und Programmierabläufe müssen sowohl in Pre-Silicon- als auch in Post-Silicon-Testphasen getestet werden. Implementieren Sie formale Verifikation der Dekodiererlogik. Verwenden Sie umfassende Testvektoren, die alle möglichen Sicherheitskennungswerte abdecken. Überprüfen Sie Dekodierer-Wahrheitstabellen auf Vollständigkeit.
Häufige Auswirkungen
| Auswirkung | Details |
|---|---|
| Vertraulichkeit | Bereich: Vertraulichkeit Unbefugter Lesezugriff auf geschützten Speicher und Assets. |
| Integrität | Bereich: Integrität Speichermodifikation durch nicht vertrauenswürdige Agenten. |
| Verfügbarkeit | Bereich: Verfügbarkeit Denial of Service durch Ressourcenverbrauch. |
| Zugriffskontrolle | Bereich: Zugriffskontrolle Privilegieneskalation, Identitätsübernahme, unbefugte Codeausführung. |
Beispielcode und Lösung
Verwundbarer Code
// VERWUNDBAR: Unvollständige Dekodierung der Sicherheitskennung
module vulnerable_security_decoder (
input wire [31:0] bus_transaction,
output reg [1:0] security_identifier,
output reg access_granted
);
// Sicherheitskennung ist in Bits [15:14]
// 00 = Nicht vertrauenswürdig (Master_0)
// 01 = Eingeschränktes Vertrauen (Master_1)
// 10 = Vertrauenswürdig (Master_2)
// 11 = Hoch vertrauenswürdig (Master_3)
// VERWUNDBAR: Nur Bit [14] wird geprüft, Bit [15] ignoriert
always @(*) begin
if (bus_transaction[14] == 1'b1) begin
// VERWUNDBAR: Gewährt fälschlicherweise vertrauenswürdigen Status
// Master_1 (01) wird gleich wie Master_3 (11) behandelt
security_identifier = 2'b01; // Nimmt eingeschränktes Vertrauen an
end else begin
security_identifier = 2'b00; // Nicht vertrauenswürdig
end
end
// VERWUNDBAR: Vereinfachte Zugriffsprüfung
always @(*) begin
// Zugriff gewähren bei jeder Vertrauensstufe
access_granted = (security_identifier != 2'b00);
end
// Angriffsszenario:
// Master_0 (nicht vertrauenswürdig, bits[15:14] = 00) - korrekt abgelehnt
// Master_1 (eingeschränkt, bits[15:14] = 01) - gewährt (Bit 14 = 1)
// Master_2 (vertrauenswürdig, bits[15:14] = 10) - FÄLSCHLICH abgelehnt (Bit 14 = 0)
// Master_3 (hoch vertrauenswürdig, bits[15:14] = 11) - gewährt (Bit 14 = 1)
//
// Dies erlaubt Master_1 den gleichen Zugriff wie Master_3!
endmodule
// VERWUNDBAR: AES-Schlüsselregister-Zugriff mit fehlerhaftem Dekodierer
module vulnerable_aes_key_access (
input wire clk,
input wire rst_n,
input wire [31:0] bus_transaction,
input wire [7:0] address,
input wire read_enable,
output reg [127:0] aes_key_out,
output reg access_fault
);
reg [127:0] aes_key;
reg [1:0] decoded_security_id;
// AES-Schlüsselregister an Adresse 0x80
localparam AES_KEY_ADDR = 8'h80;
// VERWUNDBAR: Unvollständiger Dekodierer
always @(*) begin
// Nur ein Bit wird geprüft!
decoded_security_id = bus_transaction[14] ? 2'b01 : 2'b00;
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
aes_key_out <= 128'b0;
access_fault <= 1'b0;
end else if (read_enable && (address == AES_KEY_ADDR)) begin
// VERWUNDBAR: Fehlerhafte Sicherheitsprüfung
if (decoded_security_id != 2'b00) begin
aes_key_out <= aes_key;
access_fault <= 1'b0;
end else begin
aes_key_out <= 128'b0;
access_fault <= 1'b1;
end
end
end
endmodule
// VERWUNDBAR: Software-Dekodierung der Sicherheitskennung
#include <stdint.h>
#include <stdbool.h>
#define SECURITY_UNTRUSTED 0
#define SECURITY_LIMITED 1
#define SECURITY_TRUSTED 2
#define SECURITY_HIGH_TRUST 3
// VERWUNDBAR: Unvollständige Bit-Extraktion
uint8_t vulnerable_decode_security_id(uint32_t transaction) {
// VERWUNDBAR: Nur Bit 14 wird geprüft, Bit 15 ignoriert
if (transaction & (1 << 14)) {
return SECURITY_LIMITED; // Falsch!
}
return SECURITY_UNTRUSTED;
}
// VERWUNDBAR: Zugriffskontrolle mit fehlerhaftem Dekodierer
bool vulnerable_check_access(uint32_t transaction, uint8_t resource_level) {
uint8_t security_id = vulnerable_decode_security_id(transaction);
// VERWUNDBAR: Erlaubt Umgehung durch fehlerhafte Dekodierung
return security_id >= resource_level;
}
// VERWUNDBAR: Maske ist unvollständig
#define SECURITY_ID_MASK_VULNERABLE (1 << 14) // Nur ein Bit!
uint8_t vulnerable_extract_security_id(uint32_t transaction) {
// VERWUNDBAR: Nur ein Bit eines Zwei-Bit-Feldes extrahiert
return (transaction & SECURITY_ID_MASK_VULNERABLE) >> 14;
}
Sichere Lösung
// SICHER: Vollständige Dekodierung der Sicherheitskennung
module secure_security_decoder (
input wire [31:0] bus_transaction,
output reg [1:0] security_identifier,
output reg access_granted,
output reg [3:0] access_level
);
// Sicherheitskennung ist in Bits [15:14]
// 00 = Nicht vertrauenswürdig (Master_0)
// 01 = Eingeschränktes Vertrauen (Master_1)
// 10 = Vertrauenswürdig (Master_2)
// 11 = Hoch vertrauenswürdig (Master_3)
// SICHER: Vollständiges 2-Bit-Feld prüfen
always @(*) begin
case (bus_transaction[15:14])
2'b00: begin
security_identifier = 2'b00;
access_level = 4'b0001; // Stufe 0: Nur öffentliche Ressourcen
end
2'b01: begin
security_identifier = 2'b01;
access_level = 4'b0011; // Stufe 1: Eingeschränkter Zugriff
end
2'b10: begin
security_identifier = 2'b10;
access_level = 4'b0111; // Stufe 2: Vertrauenswürdiger Zugriff
end
2'b11: begin
security_identifier = 2'b11;
access_level = 4'b1111; // Stufe 3: Vollzugriff
end
default: begin
// SICHER: Sicherer Standard für undefinierte Zustände
security_identifier = 2'b00;
access_level = 4'b0000; // Alles verweigern
end
endcase
end
// SICHER: Explizite Zugriffsentscheidung pro Stufe
always @(*) begin
access_granted = (security_identifier != 2'b00);
end
endmodule
// SICHER: AES-Schlüsselregister-Zugriff mit korrektem Dekodierer
module secure_aes_key_access (
input wire clk,
input wire rst_n,
input wire [31:0] bus_transaction,
input wire [7:0] address,
input wire read_enable,
output reg [127:0] aes_key_out,
output reg access_fault
);
reg [127:0] aes_key;
reg [1:0] decoded_security_id;
// AES-Schlüsselregister an Adresse 0x80
localparam AES_KEY_ADDR = 8'h80;
// Erforderliche Sicherheitsstufe für AES-Schlüsselzugriff
localparam REQUIRED_LEVEL = 2'b10; // Vertrauenswürdig oder höher
// SICHER: Vollständiger Dekodierer
always @(*) begin
decoded_security_id = bus_transaction[15:14]; // Vollständiges 2-Bit-Feld
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
aes_key_out <= 128'b0;
access_fault <= 1'b0;
end else if (read_enable && (address == AES_KEY_ADDR)) begin
// SICHER: Ordnungsgemäße Sicherheitsstufenprüfung
if (decoded_security_id >= REQUIRED_LEVEL) begin
aes_key_out <= aes_key;
access_fault <= 1'b0;
end else begin
aes_key_out <= 128'b0;
access_fault <= 1'b1;
end
end
end
endmodule
// SICHER: Parametrisierter Dekodierer mit Validierung
module secure_parameterized_decoder #(
parameter SECURITY_BITS = 2,
parameter FIELD_MSB = 15,
parameter FIELD_LSB = 14
) (
input wire [31:0] bus_transaction,
input wire [SECURITY_BITS-1:0] required_level,
output wire [SECURITY_BITS-1:0] security_id,
output wire access_granted
);
// SICHER: Vollständiges Feld extrahieren
assign security_id = bus_transaction[FIELD_MSB:FIELD_LSB];
// SICHER: Gegen erforderliche Stufe vergleichen
assign access_granted = (security_id >= required_level);
// Assertions für Verifikation
// synthesis translate_off
initial begin
// Feldbreite stimmt mit Parameter überein
if ((FIELD_MSB - FIELD_LSB + 1) != SECURITY_BITS) begin
$error("Feldbreiten-Nichtübereinstimmung!");
end
end
// synthesis translate_on
endmodule
// SICHER: Vollständige Software-Dekodierung der Sicherheitskennung
#include <stdint.h>
#include <stdbool.h>
#include <assert.h>
#define SECURITY_UNTRUSTED 0
#define SECURITY_LIMITED 1
#define SECURITY_TRUSTED 2
#define SECURITY_HIGH_TRUST 3
// SICHER: Vollständige Bitmaske für 2-Bit-Feld
#define SECURITY_ID_MASK (0x3 << 14) // Bits 15:14
#define SECURITY_ID_SHIFT 14
// SICHER: Vollständige Sicherheitskennung extrahieren
uint8_t secure_decode_security_id(uint32_t transaction) {
// SICHER: Beide Bits des Sicherheitsfeldes extrahieren
return (transaction & SECURITY_ID_MASK) >> SECURITY_ID_SHIFT;
}
// SICHER: Zugriffskontrolle mit ordnungsgemäßer Dekodierung
bool secure_check_access(uint32_t transaction, uint8_t required_level) {
// SICHER: required_level validieren
if (required_level > SECURITY_HIGH_TRUST) {
return false; // Ungültige Stufe, Zugriff verweigern
}
uint8_t security_id = secure_decode_security_id(transaction);
// SICHER: Ordnungsgemäßer Vergleich
return security_id >= required_level;
}
// SICHER: Dekodierer mit Validierung
typedef struct {
uint8_t security_level;
bool valid;
const char* description;
} decoded_security_t;
decoded_security_t secure_decode_with_validation(uint32_t transaction) {
decoded_security_t result;
// SICHER: Vollständiges Feld extrahieren
uint8_t raw_id = (transaction & SECURITY_ID_MASK) >> SECURITY_ID_SHIFT;
switch (raw_id) {
case SECURITY_UNTRUSTED:
result.security_level = SECURITY_UNTRUSTED;
result.description = "Nicht vertrauenswürdig";
result.valid = true;
break;
case SECURITY_LIMITED:
result.security_level = SECURITY_LIMITED;
result.description = "Eingeschränktes Vertrauen";
result.valid = true;
break;
case SECURITY_TRUSTED:
result.security_level = SECURITY_TRUSTED;
result.description = "Vertrauenswürdig";
result.valid = true;
break;
case SECURITY_HIGH_TRUST:
result.security_level = SECURITY_HIGH_TRUST;
result.description = "Hohes Vertrauen";
result.valid = true;
break;
default:
result.security_level = SECURITY_UNTRUSTED;
result.description = "Unbekannt - Standard Nicht vertrauenswürdig";
result.valid = false;
break;
}
return result;
}
// SICHER: Ressourcenzugriff mit vollständiger Validierung
typedef struct {
uint32_t address;
uint8_t required_level;
const char* name;
} protected_resource_t;
bool secure_resource_access(uint32_t transaction, const protected_resource_t* resource) {
if (resource == NULL) {
return false;
}
decoded_security_t decoded = secure_decode_with_validation(transaction);
// SICHER: Zugriffsversuche für Audit protokollieren
log_access_attempt(resource->name, decoded.description,
decoded.security_level >= resource->required_level);
// SICHER: Dekodierung war erfolgreich
if (!decoded.valid) {
return false; // Bei ungültiger Sicherheitskennung verweigern
}
return decoded.security_level >= resource->required_level;
}
CVE-Beispiele
- CVE-2021-33101: Dekodierer in bestimmten Intel-Prozessoren interpretierte Sicherheitskennungen falsch, was möglicherweise Privilegieneskalation ermöglichte.
Verwandte CWEs
- CWE-284: Unsachgemäße Zugriffskontrolle (übergeordnet)
- CWE-1294: Unsicherer Sicherheitskennungsmechanismus (übergeordnet)
- CWE-1292: Fehlerhafte Konvertierung von Sicherheitskennungen (verwandt)
- CWE-863: Fehlerhafte Autorisierung (verwandt)
Referenzen
- MITRE Corporation. "CWE-1290: Incorrect Decoding of Security Identifiers." https://cwe.mitre.org/data/definitions/1290.html
- ARM. "AMBA Bus Protocol Specifications"
- CERT. "Hardware Security Guidelines"