Unsachgemäßer Schutz gegen Spannungs- und Taktglitches
Beschreibung
Unsachgemäßer Schutz gegen Spannungs- und Taktglitches tritt auf, wenn einem Gerät geeignete Schaltungen oder Sensoren fehlen, um Spannungs- und Taktglitches zu erkennen und abzuwehren, die sensible Informationen oder Software kompromittieren könnten. Geräte, die Sicherheitsfunktionen wie Secure Boot implementieren, etablieren eine Vertrauenskette durch Signaturüberprüfung vor der Ausführung nachfolgender Stufen. Hardware und Firmware arbeiten zusammen, um sichere Zustände über Zugriffskontrolleinstellungen zu konfigurieren. Ohne geeignete Abwehrmaßnahmen können Angreifer jedoch Fault-Injection-Techniken -- insbesondere Spannungs- und Taktglitches -- ausnutzen, um diese Sicherheitsmaßnahmen zu umgehen.
Risiko
Anfälligkeit für Glitch-Angriffe hat schwerwiegende Sicherheitsauswirkungen. Secure Boot kann umgangen werden. Signaturüberprüfung kann ausgehebelt werden. Zugriffskontrollentscheidungen können korrumpiert werden. Kryptografische Operationen können falsche Ergebnisse liefern. Sicherheitszustandsautomaten können Zustände überspringen. Debug-Sperren können umgangen werden. Privilege Escalation kann möglich sein. Beliebige Codeausführung kann erreicht werden.
Lösung
Implementieren Sie Tunable Replica Circuits (TRCs) oder Razor-Flip-Flops zur Erkennung von Timing-Verletzungen. Setzen Sie plattformweite Glitch-Erkennungssensoren ein. Fügen Sie Redundanz zu sicherheitskritischen Codeabschnitten hinzu. Implementieren Sie doppelte Überprüfung von Sicherheitsentscheidungen. Verwenden Sie fehlererkennende Codes für kritische Daten. Fügen Sie Spannungs- und Taktüberwachung hinzu. Gestalten Sie Sicherheitsüberprüfungen glitch-resistent. Erwägen Sie Hardware-Sicherheitsmodule für kritische Operationen.
Häufige Auswirkungen
| Auswirkung | Details |
|---|---|
| Vertraulichkeit, Integrität, Verfügbarkeit, Zugriffskontrolle | Umfang: Alle Mehrere Auswirkungen einschließlich Privilege Escalation, Umgehung von Schutzmechanismen, unbefugtem Speicherzugriff und beliebiger Codeausführung. |
Beispielcode und Lösung
Verwundbarer Code
// VERWUNDBAR: Einzelne Sicherheitsüberprüfung leicht durch Glitch umgehbar
bool verify_firmware_signature(const uint8_t* firmware, size_t size,
const uint8_t* signature) {
// VERWUNDBAR: Einzelner Ausfallpunkt für Glitch-Angriff
bool valid = crypto_verify_signature(firmware, size, signature, public_key);
if (valid) { // <-- GLITCH-ZIEL: Diese Prüfung überspringen
return true;
} else {
return false;
}
}
void vulnerable_secure_boot(void) {
load_firmware_to_memory();
// VERWUNDBAR: Einzelne Signaturprüfung
if (verify_firmware_signature(firmware, fw_size, fw_signature)) {
// Angreifer glitcht hier, um Überprüfung zu überspringen
execute_firmware();
} else {
halt_boot();
}
}
// VERWUNDBAR: Sicherheitsentscheidung basierend auf einzelnem Vergleich
void vulnerable_password_check(const char* input) {
// VERWUNDBAR: Einzelner Vergleich, Glitch kann umgehen
if (strcmp(input, stored_password) == 0) { // <-- GLITCH-ZIEL
grant_access();
} else {
deny_access();
}
}
// VERWUNDBAR: Sicherheitsflag leicht korrumpierbar
volatile bool security_enabled = true;
void vulnerable_security_gate(void) {
// VERWUNDBAR: Einzelne Flag-Prüfung
if (security_enabled) { // <-- GLITCH kann dieses Lesen korrumpieren
enforce_security_policy();
}
// Wenn Glitch security_enabled als false liest, Sicherheit umgangen
}
// VERWUNDBAR: Sicherheitszustandsautomat ohne Glitch-Schutz
module vulnerable_secure_boot_fsm (
input wire clk,
input wire reset_n,
input wire signature_valid,
output reg boot_authorized,
output reg [2:0] boot_state
);
parameter IDLE = 3'h0;
parameter VERIFY = 3'h1;
parameter AUTHORIZED = 3'h2;
parameter DENIED = 3'h3;
always @(posedge clk or negedge reset_n) begin
if (!reset_n) begin
boot_state <= IDLE;
boot_authorized <= 1'b0;
end
else begin
case (boot_state)
IDLE: begin
boot_state <= VERIFY;
end
VERIFY: begin
// VERWUNDBAR: Einzelne Prüfung, keine Redundanz
if (signature_valid) begin // <-- GLITCH-ZIEL
boot_state <= AUTHORIZED;
boot_authorized <= 1'b1;
end else begin
boot_state <= DENIED;
end
end
AUTHORIZED: begin
// Boot fortsetzen
end
DENIED: begin
// Boot angehalten
end
endcase
end
end
endmodule
// VERWUNDBAR: Keine Spannungs-/Taktglitch-Erkennung
module vulnerable_crypto_core (
input wire clk,
input wire reset_n,
input wire [127:0] data_in,
input wire [127:0] key,
output reg [127:0] data_out
);
// VERWUNDBAR: Keine Glitch-Erkennung
// Glitch während Krypto-Operation kann falsche/schwache Ausgabe erzeugen
always @(posedge clk) begin
data_out <= aes_encrypt(data_in, key);
// Wenn Takt geglitcht, könnte Verschlüsselung unvollständig/falsch sein
end
endmodule
Sichere Lösung
// SICHER: Redundante Sicherheitsüberprüfungen widerstehen Glitch-Angriffen
bool verify_firmware_signature_secure(const uint8_t* firmware, size_t size,
const uint8_t* signature) {
// SICHER: Mehrere unabhängige Überprüfungsdurchläufe
volatile bool valid1 = crypto_verify_signature(firmware, size, signature, public_key);
// Zeitlichen Jitter hinzufügen, um Glitch-Timing zu erschweren
random_delay();
volatile bool valid2 = crypto_verify_signature(firmware, size, signature, public_key);
// Andere Überprüfungsmethode
volatile bool valid3 = crypto_verify_signature_alt(firmware, size, signature, public_key);
// SICHER: Alle drei müssen übereinstimmen
if (valid1 && valid2 && valid3) {
// Dreifache Überprüfung der Entscheidung
if (valid1 == true && valid2 == true && valid3 == true) {
return true;
}
}
return false;
}
void secure_boot_with_redundancy(void) {
load_firmware_to_memory();
// SICHER: Mehrfache Überprüfung mit unterschiedlichem Timing
volatile int verify_count = 0;
for (int i = 0; i < 3; i++) {
random_delay(); // Variables Timing
if (verify_firmware_signature(firmware, fw_size, fw_signature)) {
verify_count++;
}
}
// SICHER: Alle Überprüfungen müssen bestehen
if (verify_count == 3) {
// Abschließende Prüfung vor Ausführung
if (verify_count == 3) {
execute_firmware();
}
} else {
halt_boot();
}
}
// SICHER: Glitch-resistenter Vergleich
bool secure_compare(const char* a, const char* b, size_t len) {
volatile uint8_t result = 0;
volatile uint8_t result2 = 0;
// Erster Durchlauf
for (size_t i = 0; i < len; i++) {
result |= a[i] ^ b[i];
}
random_delay();
// Zweiter Durchlauf (ändere Richtung)
for (size_t i = len; i > 0; i--) {
result2 |= a[i-1] ^ b[i-1];
}
// Beide müssen Übereinstimmung anzeigen
return (result == 0) && (result2 == 0) && (result == result2);
}
// SICHER: Sicherheitsflag mit Redundanz
volatile bool security_enabled_1 = true;
volatile bool security_enabled_2 = true;
volatile uint32_t security_checksum = SECURITY_ENABLED_CHECKSUM;
void secure_security_gate(void) {
// SICHER: Mehrere Flags und Prüfsumme
bool flag1 = security_enabled_1;
bool flag2 = security_enabled_2;
bool checksum_valid = (security_checksum == SECURITY_ENABLED_CHECKSUM);
// Alle drei müssen übereinstimmen
if (flag1 && flag2 && checksum_valid) {
if (flag1 == flag2) {
enforce_security_policy();
}
} else {
// Inkonsistenz erkannt - möglicher Angriff
security_violation_handler();
}
}
// SICHER: Sicherheitszustandsautomat mit Glitch-Erkennung
module secure_boot_fsm (
input wire clk,
input wire reset_n,
input wire signature_valid,
input wire voltage_glitch_detected,
input wire clock_glitch_detected,
output reg boot_authorized,
output reg [2:0] boot_state,
output reg security_violation
);
parameter IDLE = 3'h0;
parameter VERIFY_1 = 3'h1;
parameter VERIFY_2 = 3'h2;
parameter VERIFY_3 = 3'h3;
parameter AUTHORIZED = 3'h4;
parameter DENIED = 3'h5;
reg [2:0] verify_count;
reg [2:0] verify_pass_count;
always @(posedge clk or negedge reset_n) begin
if (!reset_n) begin
boot_state <= IDLE;
boot_authorized <= 1'b0;
security_violation <= 1'b0;
verify_count <= 3'h0;
verify_pass_count <= 3'h0;
end
// SICHER: Auf Glitch-Angriffe prüfen
else if (voltage_glitch_detected || clock_glitch_detected) begin
boot_state <= DENIED;
security_violation <= 1'b1;
boot_authorized <= 1'b0;
end
else begin
case (boot_state)
IDLE: begin
boot_state <= VERIFY_1;
verify_count <= 3'h0;
verify_pass_count <= 3'h0;
end
VERIFY_1: begin
// SICHER: Erste Überprüfung
if (signature_valid) verify_pass_count <= verify_pass_count + 1;
boot_state <= VERIFY_2;
end
VERIFY_2: begin
// SICHER: Zweite Überprüfung (anderes Timing)
if (signature_valid) verify_pass_count <= verify_pass_count + 1;
boot_state <= VERIFY_3;
end
VERIFY_3: begin
// SICHER: Dritte Überprüfung
if (signature_valid) verify_pass_count <= verify_pass_count + 1;
// SICHER: Alle drei Überprüfungen müssen bestehen
if (verify_pass_count == 3'd2 && signature_valid) begin
boot_state <= AUTHORIZED;
boot_authorized <= 1'b1;
end else begin
boot_state <= DENIED;
end
end
AUTHORIZED: begin
// Weiterhin auf Glitches überwachen
if (voltage_glitch_detected || clock_glitch_detected) begin
boot_authorized <= 1'b0;
security_violation <= 1'b1;
end
end
DENIED: begin
boot_authorized <= 1'b0;
end
endcase
end
end
endmodule
// SICHER: Glitch-Erkennungsschaltung
module glitch_detector (
input wire clk,
input wire reset_n,
input wire voltage_sense,
input wire clock_in,
output reg voltage_glitch,
output reg clock_glitch
);
// Spannungsglitch-Erkennung mittels Fensterkomparator
reg [7:0] voltage_history;
parameter VOLTAGE_MIN = 8'd100;
parameter VOLTAGE_MAX = 8'd200;
always @(posedge clk or negedge reset_n) begin
if (!reset_n) begin
voltage_glitch <= 1'b0;
end
else begin
// Spannung außerhalb des Normalbereichs erkennen
if (voltage_sense < VOLTAGE_MIN || voltage_sense > VOLTAGE_MAX) begin
voltage_glitch <= 1'b1;
end
end
end
// Taktglitch-Erkennung nach Razor-Flip-Flop-Konzept
reg clock_sample_1, clock_sample_2;
reg clock_edge_count;
always @(posedge clk or negedge reset_n) begin
if (!reset_n) begin
clock_glitch <= 1'b0;
clock_sample_1 <= 1'b0;
clock_sample_2 <= 1'b0;
end
else begin
clock_sample_1 <= clock_in;
clock_sample_2 <= clock_sample_1;
// Unerwartete Taktflanken erkennen
if (clock_sample_1 != clock_sample_2) begin
clock_edge_count <= clock_edge_count + 1;
if (clock_edge_count > expected_edges) begin
clock_glitch <= 1'b1;
end
end
end
end
endmodule
CVE-Beispiele
- CVE-2019-17391: Secure-Boot-Umgehung durch fehlenden Anti-Glitch-Schutz
- CVE-2021-33478: Boot-Shell-Zugriff durch Impulsangriffe
- Plundervolt- und CLKSCREW-Angriffe, die DVFS-Schnittstellen ausnutzen
Verwandte CWEs
- CWE-1384: Unsachgemäße Behandlung physischer oder umgebungsbedingter Zustände (übergeordnet)
- CWE-1332: Unsachgemäße Behandlung von Fehlern, die zu Instruktionsübersprüngen führen (gleichrangig)
- CWE-1256: Privilegierter Zugriff auf Energieverwaltungsfunktionen (verwandt)
Referenzen
- MITRE Corporation. "CWE-1247: Improper Protection Against Voltage and Clock Glitches." https://cwe.mitre.org/data/definitions/1247.html
- Plundervolt Attack Research
- CLKSCREW: Exploiting DVFS for Security Bypass