Nicht initialisierter Wert bei Reset für Register mit Sicherheitseinstellungen
Beschreibung
Nicht initialisierter Wert bei Reset für Register mit Sicherheitseinstellungen tritt auf, wenn sicherheitskritische Logik beim Systemreset nicht auf einen bekannten Wert gesetzt wird. Während des Geratestarts erzeugen nicht initialisierte Register ein Verwundbarkeitsfenster, bevor Sicherheitsmechanismen ordnungsgemäß eingerichtet sind. Register können nach dem Reset zufallige oder unbestimmte Werte enthalten, wenn sie nicht explizit initialisiert werden, was das System potenziell in einem unsicheren Zustand belasst, bis die Software die Initialisierung abschließt.
Risiko
Nicht initialisierte Sicherheitsregister haben schwerwiegende Sicherheitsauswirkungen. Debug-Schnittstellen können entsperrt sein. Schutzmechanismen können deaktiviert sein. Zugriffskontrollen können unwirksam sein. Sicherheitsrichtlinien können standardmäßig permissiv sein. Authentifizierung kann umgangen werden. Kryptografische Funktionen können kompromittiert sein. Angreifer können das Initialisierungsfenster ausnutzen. Wiederholte Resets können probabilistisch unsichere Zustände erreichen.
Lösung
Alle Register, die sicherheitskritische Informationen enthalten, sollten beim Reset auf einen bestimmten sicheren Wert gesetzt werden. Fuhren Sie Design-Prüfungen durch, um nicht initialisierte Flip-Flops in sicherheitskritischen Funktionen zu identifizieren. Verwenden Sie Hardware-Reset-Werte, die standardmäßig den sichersten Zustand einnehmen. Implementieren Sie sichere Standardinitialisierung. Verifizieren Sie das Reset-Verhalten durch Simulation und Tests. Dokumentieren Sie alle Sicherheitsregister-Reset-Werte.
Häufige Auswirkungen
| Auswirkung | Details |
|---|---|
| Zugriffskontrolle | Umfang: Zugriffskontrolle Schutzmechanismus umgehen - Nicht initialisierte Register können unbefugten Zugriff ermöglichen. |
| Authentifizierung | Umfang: Authentifizierung Authentifizierung umgehen - Sicherheitsprüfungen können vor der Initialisierung umgangen werden. |
| Autorisierung | Umfang: Autorisierung Berechtigungen erlangen - Angreifer können während des unsicheren Fensters erhöhte Berechtigungen erlangen. |
Beispielcode und Lösung
Verwundbarer Code
// VERWUNDBAR: JTAG-Sperre ohne Reset-Initialisierung
module vulnerable_jtag_controller (
input wire clk,
input wire reset_n,
input wire jtag_tck,
input wire jtag_tms,
input wire jtag_tdi,
output wire jtag_tdo,
// Sperrsteuerung
input wire lock_command,
output reg jtag_locked
);
// VERWUNDBAR: Kein Reset-Wert für jtag_locked
// Nach dem Reset hat jtag_locked einen unbestimmten Wert
always @(posedge clk) begin
if (lock_command) begin
jtag_locked <= 1'b1;
end
// VERWUNDBAR: Keine Reset-Behandlung
// jtag_locked könnte nach dem Einschalten 0 oder 1 sein
end
// VERWUNDBAR: Debug-Zugriff hangt von nicht initialisiertem Register ab
wire debug_allowed = !jtag_locked;
// Angriff: Angreifer setzt Gerat wiederholt zurück
// Irgendwann startet jtag_locked als 0
// Debug-Schnittstelle ist zuganglich!
endmodule
// VERWUNDBAR: Sicherheitskonfiguration ohne Initialisierung
module vulnerable_security_config (
input wire clk,
input wire reset_n,
input wire [7:0] config_addr,
input wire [31:0] config_data,
input wire config_write,
output reg secure_boot_enabled,
output reg encryption_enabled,
output reg debug_disabled,
output reg tamper_response_enabled
);
// VERWUNDBAR: Keine Reset-Initialisierung
// Alle Sicherheitseinstellungen sind nach dem Reset unbestimmt
always @(posedge clk) begin
if (config_write) begin
case (config_addr)
8'h00: secure_boot_enabled <= config_data[0];
8'h01: encryption_enabled <= config_data[0];
8'h02: debug_disabled <= config_data[0];
8'h03: tamper_response_enabled <= config_data[0];
endcase
end
// VERWUNDBAR: Keine Reset-Klausel
// Einstellungen sind undefiniert bis Software sie konfiguriert
end
// System arbeitet nach dem Reset mit undefinierter Sicherheitslage
// Bis Software die Initialisierungssequenz ausführt
endmodule
// VERWUNDBAR: Zugriffskontrolle ohne Reset
module vulnerable_access_control (
input wire clk,
input wire reset_n,
input wire [3:0] agent_id,
input wire [31:0] address,
input wire access_request,
output reg access_granted
);
// Zugriffsberechtigungsbits - eines pro Agent
reg [15:0] permission_bits;
// VERWUNDBAR: permission_bits nicht beim Reset initialisiert
// Konnte alles 1en sein (alles erlaubt) oder zufallig
always @(posedge clk) begin
if (access_request) begin
// VERWUNDBAR: Prüfung gegen nicht initialisierte Berechtigungen
access_granted <= permission_bits[agent_id];
end
end
endmodule
// VERWUNDBAR: Software verlässt sich auf Hardware-Initialisierung
#include <stdint.h>
#define SECURITY_CONFIG_BASE 0x40000000
typedef struct {
volatile uint32_t secure_boot;
volatile uint32_t encryption;
volatile uint32_t debug_lock;
volatile uint32_t tamper_response;
} security_config_t;
void vulnerable_boot(void) {
security_config_t* config = (security_config_t*)SECURITY_CONFIG_BASE;
// VERWUNDBAR: Nimmt an, dass Hardware Register auf sichere Werte initialisiert hat
// Aber Hardware hat möglicherweise keine Reset-Initialisierung
if (config->secure_boot) {
// Kann nie wahr sein, wenn Register nicht initialisiert ist
verify_firmware_signature();
}
// VERWUNDBAR: Nicht initialisiertes Register lesen
if (config->debug_lock == 0) {
// Debug erscheint entsperrt aufgrund nicht initialisiertem Register
// Angreifer kann auf Debug-Schnittstelle zugreifen!
enable_debug_interface();
}
// System kann in unsicherem Zustand booten
boot_firmware();
}
// VERWUNDBAR: Race Condition bei Initialisierung
void vulnerable_late_initialization(void) {
security_config_t* config = (security_config_t*)SECURITY_CONFIG_BASE;
// VERWUNDBAR: Sicherheitskonfiguration erfolgt spat im Boot-Prozess
// Verwundbarkeitsfenster existiert vom Reset bis hierher
// ... viele andere Initialisierungsschritte zuerst ...
// Endlich Sicherheit konfigurieren (zu spat!)
config->secure_boot = 1;
config->encryption = 1;
config->debug_lock = 1;
config->tamper_response = 1;
}
Sichere Lösung
// SICHER: JTAG-Sperre mit sicherer Reset-Initialisierung
module secure_jtag_controller (
input wire clk,
input wire reset_n,
input wire jtag_tck,
input wire jtag_tms,
input wire jtag_tdi,
output wire jtag_tdo,
input wire lock_command,
input wire unlock_auth, // Authentifizierte Entsperrung
output reg jtag_locked
);
// SICHER: Expliziter Reset auf gesperrten Zustand
always @(posedge clk or negedge reset_n) begin
if (!reset_n) begin
// SICHER: Standardmäßig gesperrter (sicherer) Zustand bei Reset
jtag_locked <= 1'b1;
end
else begin
if (lock_command) begin
jtag_locked <= 1'b1;
end
else if (unlock_auth) begin
// Nur mit ordnungsgemäßer Authentifizierung entsperren
jtag_locked <= 1'b0;
end
end
end
// Debug nur erlaubt wenn explizit entsperrt
wire debug_allowed = !jtag_locked;
endmodule
// SICHER: Sicherheitskonfiguration mit sicheren Standardwerten
module secure_security_config (
input wire clk,
input wire reset_n,
input wire [7:0] config_addr,
input wire [31:0] config_data,
input wire config_write,
input wire privileged_access, // Nur privilegiert kann ändern
output reg secure_boot_enabled,
output reg encryption_enabled,
output reg debug_disabled,
output reg tamper_response_enabled,
output reg config_locked // Weitere Änderungen verhindern
);
// SICHER: Alle Sicherheitseinstellungen auf sichere Standardwerte bei Reset initialisiert
always @(posedge clk or negedge reset_n) begin
if (!reset_n) begin
// SICHER: Sichere Standardwerte bei Reset
secure_boot_enabled <= 1'b1; // Secure Boot AN
encryption_enabled <= 1'b1; // Verschlüsselung AN
debug_disabled <= 1'b1; // Debug AUS
tamper_response_enabled <= 1'b1; // Manipulationsreaktion AN
config_locked <= 1'b0; // Initiale Konfiguration erlauben
end
else if (config_write && privileged_access && !config_locked) begin
case (config_addr)
8'h00: secure_boot_enabled <= config_data[0];
8'h01: encryption_enabled <= config_data[0];
8'h02: debug_disabled <= config_data[0];
8'h03: tamper_response_enabled <= config_data[0];
8'hFF: config_locked <= config_data[0]; // Konfiguration sperren
endcase
end
end
endmodule
// SICHER: Zugriffskontrolle mit sicherem Reset
module secure_access_control (
input wire clk,
input wire reset_n,
input wire [3:0] agent_id,
input wire [31:0] address,
input wire access_request,
input wire privileged_config,
input wire [15:0] new_permissions,
output reg access_granted
);
// Zugriffsberechtigungsbits
reg [15:0] permission_bits;
// SICHER: Auf restriktivste Berechtigungen initialisieren
always @(posedge clk or negedge reset_n) begin
if (!reset_n) begin
// SICHER: Standardmäßig alles verweigern außer Agent 0 (sicherer Master)
permission_bits <= 16'h0001;
access_granted <= 1'b0;
end
else begin
// Berechtigungen nur aus privilegiertem Kontext aktualisieren
if (privileged_config) begin
permission_bits <= new_permissions;
end
if (access_request) begin
access_granted <= permission_bits[agent_id];
end
end
end
endmodule
// SICHER: Umfassende Sicherheitsinitialisierungs-Verifizierung
module security_init_checker (
input wire clk,
input wire reset_n,
input wire [31:0] security_reg_0,
input wire [31:0] security_reg_1,
input wire [31:0] security_reg_2,
input wire [31:0] security_reg_3,
output reg init_verified,
output reg init_failed
);
// Erwartete sichere Werte nach Reset
parameter EXPECTED_REG_0 = 32'h0000_0001; // Secure Boot
parameter EXPECTED_REG_1 = 32'h0000_0001; // Verschlüsselung
parameter EXPECTED_REG_2 = 32'h0000_0001; // Debug gesperrt
parameter EXPECTED_REG_3 = 32'h0000_0001; // Manipulationserkennung aktiviert
always @(posedge clk or negedge reset_n) begin
if (!reset_n) begin
init_verified <= 1'b0;
init_failed <= 1'b0;
end
else begin
// SICHER: Sicherheitsregister nach Reset verifizieren
if (security_reg_0 == EXPECTED_REG_0 &&
security_reg_1 == EXPECTED_REG_1 &&
security_reg_2 == EXPECTED_REG_2 &&
security_reg_3 == EXPECTED_REG_3) begin
init_verified <= 1'b1;
init_failed <= 1'b0;
end
else begin
init_verified <= 1'b0;
init_failed <= 1'b1;
end
end
end
endmodule
// SICHER: Software mit ordnungsgemäßer Initialisierungsbehandlung
#include <stdint.h>
#include <stdbool.h>
#define SECURITY_CONFIG_BASE 0x40000000
typedef struct {
volatile uint32_t secure_boot;
volatile uint32_t encryption;
volatile uint32_t debug_lock;
volatile uint32_t tamper_response;
volatile uint32_t init_status;
} security_config_t;
// SICHER: Hardware-Initialisierung verifizieren
bool verify_security_init(void) {
security_config_t* config = (security_config_t*)SECURITY_CONFIG_BASE;
// SICHER: Verifizieren dass Hardware auf sichere Standardwerte initialisiert wurde
if (config->secure_boot != 1) {
log_error("Secure Boot nicht initialisiert");
return false;
}
if (config->encryption != 1) {
log_error("Verschlüsselung nicht initialisiert");
return false;
}
if (config->debug_lock != 1) {
log_error("Debug nicht standardmäßig gesperrt");
return false;
}
if (config->tamper_response != 1) {
log_error("Manipulationsreaktion nicht initialisiert");
return false;
}
return true;
}
void secure_boot(void) {
// SICHER: Sicherheitsinitialisierung ZUERST verifizieren
if (!verify_security_init()) {
// Hardware nicht ordnungsgemäß initialisiert - anhalten
log_error("Sicherheitsinitialisierung fehlgeschlagen - Anhalten");
secure_halt();
return;
}
security_config_t* config = (security_config_t*)SECURITY_CONFIG_BASE;
// Jetzt sicher fortzufahren - Hardware ist in bekanntem sicherem Zustand
if (config->secure_boot) {
if (!verify_firmware_signature()) {
log_error("Firmware-Signaturverifizierung fehlgeschlagen");
secure_halt();
return;
}
}
// Mit Boot fortfahren
boot_firmware();
}
// SICHER: Fruhe Sicherheitsinitialisierung
void __attribute__((section(".init"))) early_security_init(void) {
security_config_t* config = (security_config_t*)SECURITY_CONFIG_BASE;
// SICHER: Sichere Standardwerte sofort beim Boot setzen
// Sogar vor der C-Laufzeit-Initialisierung
config->secure_boot = 1;
config->encryption = 1;
config->debug_lock = 1;
config->tamper_response = 1;
// Memory Barrier um sicherzustellen, dass Schreibvorgange abgeschlossen sind
__asm__ volatile("dmb sy" ::: "memory");
// Verifizieren dass Schreibvorgange wirksam wurden
if (config->debug_lock != 1) {
// Sperren fehlgeschlagen - anhalten
while(1) { __asm__ volatile("wfi"); }
}
}
CVE-Beispiele
Schwachstellen bei der Register-Initialisierung wurden in verschiedenen Hardware-Designs gefunden, bei denen Sicherheitsregister in unbestimmten Zuständen gestartet wurden, was Angreifern ermöglichte, Gerate wiederholt zurückzusetzen, bis eine unsichere Konfiguration erreicht wurde.
Verwandte CWEs
- CWE-909: Fehlende Initialisierung von Ressourcen (ubergeordnet)
- CWE-1206: Strom-, Takt-, Thermal- und Reset-Bedenken (Kategorie)
- CWE-1304: Unsachgemäß erhaltene Integritat des Hardware-Konfigurationszustands (verwandt)
- CAPEC-74: Zustandsmanipulation (Angriffsmuster)
Referenzen
- MITRE Corporation. "CWE-1271: Uninitialized Value on Reset for Registers Holding Security Settings." https://cwe.mitre.org/data/definitions/1271.html
- ARM. "TrustZone Security Extensions Reset Behavior"
- Intel. "Platform Security Best Practices"