Fehlerhafte Auswahl von Fuse-Werten
Beschreibung
Fehlerhafte Auswahl von Fuse-Werten tritt auf, wenn ein Produkt auf eine nicht durchgebrannte Fuse angewiesen ist, um einen sicheren Systemzustand herzustellen. Da Fuses standardmäßig auf Logik 0 (nicht durchgebrannt) stehen und auf Logik 1 durchgebrannt, aber nicht einfach zurückgesetzt werden können, erzeugt die Verwendung negativer Logik eine Schwachstelle. Fuses speichern Sicherheitskonfigurationsdaten und sind gerichtet -- einmal auf 1 durchgebrannt, können sie ohne Spezialausrüstung nicht auf 0 zurückkehren. Die Schwachstelle entsteht, wenn die Sicherheitslogik des Systems davon abhängt, dass Fuses nicht durchgebrannt bleiben, wodurch Angreifer Fuses durchbrennen und das System in einen unsicheren Zustand überführen können.
Risiko
Fehlerhafte Fuse-Logik hat schwerwiegende Sicherheitsauswirkungen. Secure Boot kann durch Durchbrennen von Fuses deaktiviert werden. Debug-Schnittstellen können wieder aktiviert werden. Sicherheitsfunktionen können umgangen werden. JTAG-Zugriff kann entsperrt werden. Firmware-Signaturüberprüfung kann übersprungen werden. Produktionssicherheit kann kompromittiert werden. Geräteintegrität kann dauerhaft beschädigt werden. Angreifer erlangen persistenten Zugang durch Hardware-Modifikation.
Lösung
Entwerfen Sie Logik so, dass durchgebrannte Fuses das Produkt nicht in einen ausnutzbaren unsicheren Zustand überführen. Verwenden Sie positive Logik, bei der die Sicherheit beibehalten oder erhöht wird, wenn Fuses durchgebrannt werden. Stellen Sie sicher, dass der Standard-Zustand (nicht durchgebrannt) der weniger sichere Zustand ist. Lassen Sie durchgebrannte Fuses Sicherheitsfunktionen aktivieren statt deaktivieren. Implementieren Sie redundante Fuse-Prüfungen. Fügen Sie Manipulationserkennung für Fuse-Manipulation hinzu. Verwenden Sie Fuse-Redundanz mit Mehrheitsentscheidung.
Häufige Auswirkungen
| Auswirkung | Details |
|---|---|
| Zugriffskontrolle | Umfang: Zugriffskontrolle Schutzmechanismus umgehen - Wenn Sicherheitslogik negative Logik verwendet, könnte ein Angreifer die Fuse durchbrennen und das System in einen unsicheren Zustand treiben. |
| Verfügbarkeit | Umfang: Verfügbarkeit DoS: Absturz, Beendigung oder Neustart - Fuse-Manipulation kann Systeminstabilität verursachen. |
| Vertraulichkeit | Umfang: Vertraulichkeit Unbefugter Speicherzugriff - Umgehung der Sicherheit ermöglicht Zugriff auf geschützte Daten. |
| Integrität | Umfang: Integrität Speichermodifikation oder unbefugte Codeausführung - Sicherheitsumgehung ermöglicht die Ausführung unbefugten Codes. |
Beispielcode und Lösung
Verwundbarer Code
// VERWUNDBAR: Negative Logik-Fuse für Secure Boot
module vulnerable_secure_boot_fuse (
input wire clk,
input wire reset_n,
input wire fuse_secure_boot, // 0 = Secure Boot AN, 1 = Secure Boot AUS
input wire firmware_signature_valid,
output reg boot_allowed
);
// VERWUNDBAR: Negative Logik
// Fuse standardmäßig 0 (nicht durchgebrannt) = Secure Boot aktiviert
// Angreifer kann Fuse auf 1 durchbrennen = Secure Boot deaktiviert
always @(posedge clk or negedge reset_n) begin
if (!reset_n) begin
boot_allowed <= 1'b0;
end
else begin
// VERWUNDBAR: Fuse mit negativer Logik prüfen
if (fuse_secure_boot == 1'b0) begin
// Fuse nicht durchgebrannt - Signaturüberprüfung erforderlich
boot_allowed <= firmware_signature_valid;
end
else begin
// VERWUNDBAR: Fuse durchgebrannt - Überprüfung überspringen!
// Angreifer brennt Fuse durch, um Secure Boot zu umgehen
boot_allowed <= 1'b1;
end
end
end
endmodule
// VERWUNDBAR: Debug-Sperre mit negativer Logik
module vulnerable_debug_fuse (
input wire clk,
input wire reset_n,
input wire fuse_debug_lock, // 0 = Debug gesperrt, 1 = Debug entsperrt
input wire debug_request,
output reg debug_allowed
);
// VERWUNDBAR: Negative Logik für Debug-Sperre
// Fuse standardmäßig 0 = Debug gesperrt
// Angreifer brennt Fuse auf 1 = Debug entsperrt
always @(*) begin
if (fuse_debug_lock == 1'b0) begin
// Fuse nicht durchgebrannt - Debug gesperrt
debug_allowed = 1'b0;
end
else begin
// VERWUNDBAR: Fuse durchgebrannt - Debug entsperrt!
debug_allowed = debug_request;
end
end
endmodule
// VERWUNDBAR: Sicherheitsstufen-Fuse mit falschem Standard
module vulnerable_security_level_fuse (
input wire clk,
input wire reset_n,
input wire [1:0] fuse_security_level, // 00 = höchste, 11 = niedrigste
input wire [1:0] required_level,
output reg access_allowed
);
// VERWUNDBAR: Nicht durchgebrannte Fuses (00) = höchste Sicherheit
// Angreifer kann Fuses durchbrennen, um Sicherheitsstufe zu senken
always @(*) begin
// Niedrigere Zahl = höhere Sicherheit
// VERWUNDBAR: Durchbrennen von Fuses senkt Sicherheit
if (fuse_security_level <= required_level) begin
access_allowed = 1'b1;
end
else begin
access_allowed = 1'b0;
end
end
// Angriff: Beide Fuses durchbrennen für Stufe 11 (niedrigste)
// Dies gewährt Zugriff auf alles
endmodule
// VERWUNDBAR: Firmware liest Fuse mit negativer Logik
#define FUSE_REGISTER 0x40000000
#define FUSE_SECURE_BOOT_BIT 0
uint32_t read_fuse(void) {
return *(volatile uint32_t*)FUSE_REGISTER;
}
void vulnerable_boot_check(void) {
uint32_t fuses = read_fuse();
// VERWUNDBAR: Negative Logik
// Bit 0 = 0 bedeutet Secure Boot aktiviert
// Bit 0 = 1 bedeutet Secure Boot deaktiviert
if ((fuses & (1 << FUSE_SECURE_BOOT_BIT)) == 0) {
// Fuse nicht durchgebrannt - Secure Boot durchführen
if (!verify_firmware_signature()) {
halt_boot("Signaturüberprüfung fehlgeschlagen");
}
}
else {
// VERWUNDBAR: Fuse durchgebrannt - Überprüfung überspringen
// Angreifer kann diese Fuse durchbrennen, um unsignierte Firmware zu laden
}
continue_boot();
}
// VERWUNDBAR: Debug-Aktivierungs-Fuse
void vulnerable_debug_init(void) {
uint32_t fuses = read_fuse();
// VERWUNDBAR: Fuse-Bit 1 = 0 bedeutet Debug deaktiviert
// Fuse-Bit 1 = 1 bedeutet Debug aktiviert
if (fuses & (1 << 1)) {
// VERWUNDBAR: Durchgebrannte Fuse aktiviert Debug!
enable_jtag();
enable_uart_debug();
}
}
Sichere Lösung
// SICHER: Positive Logik-Fuse für Secure Boot
module secure_boot_fuse (
input wire clk,
input wire reset_n,
input wire fuse_secure_boot, // 0 = Entwicklungsmodus, 1 = Produktion sicher
input wire firmware_signature_valid,
output reg boot_allowed
);
// SICHER: Positive Logik
// Fuse standardmäßig 0 (nicht durchgebrannt) = Entwicklungsmodus (weniger sicher)
// Fuse auf 1 durchgebrannt = Produktionsmodus (Secure Boot erforderlich)
// Angreifer kann Fuse nicht ent-brennen, um Sicherheit zu deaktivieren
always @(posedge clk or negedge reset_n) begin
if (!reset_n) begin
boot_allowed <= 1'b0;
end
else begin
// SICHER: Positive Logik - durchgebrannte Fuse erzwingt Sicherheit
if (fuse_secure_boot == 1'b1) begin
// Produktionsmodus - Signaturüberprüfung erforderlich
boot_allowed <= firmware_signature_valid;
end
else begin
// Entwicklungsmodus - kann unsigniert für Entwicklung erlauben
// Aber dies ist der STANDARD-Zustand, nicht angreifbar
boot_allowed <= 1'b1; // Oder dennoch Signatur erfordern
end
end
end
endmodule
// SICHER: Debug-Sperre mit positiver Logik
module secure_debug_fuse (
input wire clk,
input wire reset_n,
input wire fuse_debug_disable, // 0 = Debug verfügbar, 1 = Debug gesperrt
input wire debug_request,
output reg debug_allowed
);
// SICHER: Positive Logik für Debug-Sperre
// Fuse standardmäßig 0 = Debug verfügbar (Entwicklung)
// Fuse auf 1 durchgebrannt = Debug dauerhaft gesperrt (Produktion)
// Angreifer kann Fuse nicht ent-brennen, um Debug wieder zu aktivieren
always @(*) begin
if (fuse_debug_disable == 1'b1) begin
// SICHER: Durchgebrannte Fuse = Debug für immer gesperrt
debug_allowed = 1'b0;
end
else begin
// Nicht durchgebrannt = Debug verfügbar (Entwicklungsmodus-Standard)
debug_allowed = debug_request;
end
end
endmodule
// SICHER: Sicherheitsstufen-Fuse mit korrekter Kodierung
module secure_security_level_fuse (
input wire clk,
input wire reset_n,
input wire [1:0] fuse_security_level, // 00 = niedrigste, 11 = höchste
input wire [1:0] required_level,
output reg access_allowed
);
// SICHER: Nicht durchgebrannte Fuses (00) = niedrigste Sicherheit (Entwicklungsstandard)
// Durchbrennen von Fuses ERHÖHT Sicherheitsstufe
// Angreifer kann seinen Zugriff nicht durch Durchbrennen von Fuses erhöhen
always @(*) begin
// SICHER: Höherer Fuse-Wert = höhere Sicherheit
// Durchbrennen von Fuses kann nur Zugriff einschränken, nicht gewähren
if (fuse_security_level >= required_level) begin
access_allowed = 1'b1;
end
else begin
access_allowed = 1'b0;
end
end
// Angriffsversuch: Durchbrennen von Fuses erhöht Sicherheitsstufe
// Dies macht den Zugriff NUR restriktiver, nicht weniger
endmodule
// SICHER: Redundante Fuse-Prüfung
module secure_redundant_fuse (
input wire clk,
input wire reset_n,
input wire fuse_secure_a, // Primäre Secure-Boot-Fuse
input wire fuse_secure_b, // Redundante Secure-Boot-Fuse
input wire fuse_secure_c, // Zweite redundante Fuse
input wire firmware_signature_valid,
output reg boot_allowed,
output reg tamper_detected
);
// SICHER: Redundante Fuses mit Mehrheitsentscheidung verwenden
wire [1:0] secure_vote;
assign secure_vote = fuse_secure_a + fuse_secure_b + fuse_secure_c;
// SICHER: Manipulation erkennen (Fuses sollten übereinstimmen)
wire fuses_consistent;
assign fuses_consistent = (fuse_secure_a == fuse_secure_b) &&
(fuse_secure_b == fuse_secure_c);
always @(posedge clk or negedge reset_n) begin
if (!reset_n) begin
boot_allowed <= 1'b0;
tamper_detected <= 1'b0;
end
else begin
// SICHER: Auf inkonsistente Fuses prüfen (Manipulation)
if (!fuses_consistent) begin
tamper_detected <= 1'b1;
boot_allowed <= 1'b0; // Ausfallsicher
end
// SICHER: Mehrheitsentscheidung (mindestens 2 von 3)
else if (secure_vote >= 2'd2) begin
// Produktionsmodus - Signatur erforderlich
boot_allowed <= firmware_signature_valid;
end
else begin
// Entwicklungsmodus
boot_allowed <= 1'b1;
end
end
end
endmodule
// SICHER: Firmware liest Fuse mit positiver Logik
#define FUSE_REGISTER 0x40000000
#define FUSE_PRODUCTION_MODE_BIT 0
#define FUSE_DEBUG_LOCKED_BIT 1
uint32_t read_fuse(void) {
return *(volatile uint32_t*)FUSE_REGISTER;
}
void secure_boot_check(void) {
uint32_t fuses = read_fuse();
// SICHER: Positive Logik
// Bit 0 = 0 bedeutet Entwicklungsmodus (Standard)
// Bit 0 = 1 bedeutet Produktionsmodus (Secure Boot erzwungen)
if (fuses & (1 << FUSE_PRODUCTION_MODE_BIT)) {
// SICHER: Durchgebrannte Fuse = Signatur muss überprüft werden
if (!verify_firmware_signature()) {
halt_boot("Signaturüberprüfung fehlgeschlagen");
}
}
else {
// Entwicklungsmodus - Warnung protokollieren
log_warning("Läuft im Entwicklungsmodus ohne Signaturprüfung");
// Auch im Entwicklungsmodus wird Signaturüberprüfung empfohlen
}
continue_boot();
}
// SICHER: Debug-Deaktivierungs-Fuse
void secure_debug_init(void) {
uint32_t fuses = read_fuse();
// SICHER: Fuse-Bit 1 = 0 bedeutet Debug verfügbar (Entwicklungsstandard)
// Fuse-Bit 1 = 1 bedeutet Debug dauerhaft deaktiviert (Produktion)
if (fuses & (1 << FUSE_DEBUG_LOCKED_BIT)) {
// SICHER: Durchgebrannte Fuse = Debug für immer gesperrt
disable_jtag();
disable_uart_debug();
log_info("Debug-Schnittstellen dauerhaft deaktiviert");
}
else {
// Entwicklungsmodus - Debug verfügbar
enable_jtag();
enable_uart_debug();
log_warning("Debug-Schnittstellen aktiviert - Entwicklungsmodus");
}
}
// SICHER: Redundante Fuse-Prüfung
void secure_boot_redundant(void) {
uint32_t fuses = read_fuse();
// Drei redundante Fuse-Bits lesen
int fuse_a = (fuses >> 0) & 1;
int fuse_b = (fuses >> 1) & 1;
int fuse_c = (fuses >> 2) & 1;
// SICHER: Auf Manipulation prüfen (inkonsistente Fuses)
if (fuse_a != fuse_b || fuse_b != fuse_c) {
halt_boot("Fuse-Manipulation erkannt!");
}
// SICHER: Mehrheitsentscheidung
int production_mode = (fuse_a + fuse_b + fuse_c) >= 2;
if (production_mode) {
if (!verify_firmware_signature()) {
halt_boot("Signaturüberprüfung fehlgeschlagen");
}
}
}
CVE-Beispiele
Fuse-Logik-Schwachstellen wurden in verschiedenen Geräten gefunden, bei denen Angreifer Fuses durchbrennen könnten, um Secure Boot zu deaktivieren, Debug-Schnittstellen wieder zu aktivieren oder Sicherheitsfunktionen zu umgehen. Beispiele umfassen Geräte, bei denen das Durchbrennen einer einzigen Fuse die Signaturüberprüfung deaktivieren könnte.
Verwandte CWEs
- CWE-693: Versagen des Schutzmechanismus (übergeordnet)
- CWE-1278: Fehlender Schutz gegen Hardware-Reverse-Engineering (verwandt)
- CWE-1338: Unsachgemäßer Schutz gegen Hardware-Überschreiben von sicherheitskonfigurierten Fuses (verwandt)
Referenzen
- MITRE Corporation. "CWE-1253: Incorrect Selection of Fuse Values." https://cwe.mitre.org/data/definitions/1253.html
- ARM. "TrustZone Security" - Fuse-basierte Konfiguration
- NXP. "Secure Boot Architecture" - OTP Fuse Programming