Firmware nicht aktualisierbar
Beschreibung
Firmware nicht aktualisierbar tritt auf, wenn einem Produkt die Fahigkeit fehlt, Firmware zu aktualisieren oder zu patchen, um Schwachstellen oder Schwachen zu beheben. Dies erzeugt permanentes Risiko über die gesamte Lebensdauer des Gerats, die potenziell Jahre oder Jahrzehnte umfassen kann, da Verbraucher verwundbar gegenüber der Ausnutzung bekannter Schwachstellen oder zukunftig entdeckter Schwachstellen bleiben. Ohne die Möglichkeit, Firmware zu patchen oder zu aktualisieren, kann eine ausnutzbare Schwachstelle in einem ungepatchten Gerat gegen eine gesamte Geräteklasse eingesetzt werden.
Risiko
Nicht aktualisierbare Firmware hat schwerwiegende Sicherheitsauswirkungen. Bekannte Schwachstellen können nicht behoben werden. Zukunftige Schwachstellen können nicht adressiert werden. Gerate werden dauerhaft kompromittiert. Angriffswerkzeuge können für gesamte Produktlinien entwickelt werden. Botnets können verwundbare Gerate rekrutieren. Compliance-Anforderungen können verletzt werden. Produkthaftung kann zunehmen. Verbrauchervertrauen wird untergraben.
Lösung
Spezifizieren Sie Firmware-Aktualisierungsfahigkeit mit Integritatsprüfungen und Authentifizierung, um nicht vertrauenswurdige Installationen während der Anforderungsphase zu verhindern. Entwerfen Sie Gerate, die Firmware-Updates erlauben, und spezifizieren Sie Verteilungs-, Integritits- und Authentifizierungsmethoden während Architektur und Design. Implementieren Sie die erforderliche Funktionalitat für Firmware-Updates einschließlich sicherer Boot-Chain-Verifizierung. Testen Sie die Aktualisierungsfahigkeit grundlich einschließlich der Ablehnung ungültiger Images.
Häufige Auswirkungen
| Auswirkung | Details |
|---|---|
| Vertraulichkeit | Umfang: Vertraulichkeit Speicher lesen - Ungepatchte Schwachstellen ermöglichen Datendiebstahl. |
| Integritat | Umfang: Integritat Unbefugten Code ausführen - Malware kann permanent installiert werden. |
| Verfügbarkeit | Umfang: Verfügbarkeit DoS - Gerate können unbrauchbar gemacht werden. |
| Zugriffskontrolle | Umfang: Zugriffskontrolle Berechtigungen erlangen - Angreifer können volle Geratekontrolle erlangen. |
| Authentifizierung | Umfang: Authentifizierung Schutzmechanismus umgehen - Sicherheitsfunktionen können nicht verbessert werden. |
Beispielcode und Lösung
Verwundbarer Code
// VERWUNDBAR: Gerat mit nur-ROM-Firmware
module vulnerable_rom_device (
input wire clk,
input wire reset_n,
input wire [15:0] addr,
output reg [31:0] data,
// Keine Firmware-Update-Schnittstelle
output reg device_ready
);
// VERWUNDBAR: Firmware im ROM - kann nicht aktualisiert werden
reg [31:0] firmware_rom [0:16383];
// ROM wird bei der Fertigung initialisiert - ändert sich nie
initial begin
$readmemh("firmware.hex", firmware_rom);
end
always @(posedge clk or negedge reset_n) begin
if (!reset_n) begin
device_ready <= 1'b0;
end
else begin
// VERWUNDBAR: Kann nur aus ROM lesen
data <= firmware_rom[addr];
device_ready <= 1'b1;
// Kein Mechanismus zum Aktualisieren der Firmware
// Wenn Schwachstelle gefunden wird, ist Gerat permanent gefährdet
end
end
// Keine Update-Schnittstelle vorhanden
// Keine Flash-Programmierfahigkeit
// Kein Secure Boot zur Verifizierung neuer Firmware
endmodule
// VERWUNDBAR: Mikrocontroller mit gesperrtem Flash
module vulnerable_locked_mcu (
input wire clk,
input wire reset_n,
// Flash ist permanent gesperrt
input wire [15:0] flash_addr,
output reg [31:0] flash_data
);
// Flash-Speicher
reg [31:0] flash_mem [0:32767];
// VERWUNDBAR: Sperr-Fuse gebrannt - Flash kann nicht umprogrammiert werden
wire flash_locked = 1'b1; // Permanent gesperrt
always @(posedge clk or negedge reset_n) begin
if (!reset_n) begin
// Von Flash initialisieren
end
else begin
// VERWUNDBAR: Schreiboperationen blockiert
// flash_mem[flash_addr] <= write_data; // Nicht möglich
// Nur Lesen
flash_data <= flash_mem[flash_addr];
end
end
// Gerat kann keine Sicherheitsupdates empfangen
// Bekannte Schwachstellen können nicht gepatcht werden
endmodule
// VERWUNDBAR: IoT-Gerat ohne Aktualisierungsfahigkeit
#include <stdint.h>
// VERWUNDBAR: Kein Firmware-Aktualisierungsmechanismus
void vulnerable_device_main(void) {
// Gerateinitialisierung
init_hardware();
init_network();
// Hauptschleife - führt dieselbe Firmware für immer aus
while (1) {
process_sensor_data();
send_to_cloud(); // Kann Schwachstellen haben
receive_commands(); // Kann Schwachstellen haben
// Kein Weg diesen Code zu aktualisieren
// Später entdeckte Schwachstellen können nicht behoben werden
}
}
// VERWUNDBAR: Selbst wenn Schwachstelle gefunden wird, kein Fix möglich
void vulnerable_network_handler(uint8_t* data, size_t len) {
// Buffer-Overflow-Schwachstelle (CWE-120)
char buffer[64];
memcpy(buffer, data, len); // Keine Grenzprüfung
// Diese Schwachstelle kann nicht gepatcht werden
// Alle eingesetzten Gerate bleiben für immer verwundbar
process_data(buffer);
}
// VERWUNDBAR: Keine Integritatsprüfung selbst wenn Update möglich ware
void no_update_mechanism(void) {
// Kein Code fur:
// - Firmware-Updates empfangen
// - Update-Signaturen verifizieren
// - In Flash schreiben
// - In neue Firmware neustarten
}
Sichere Lösung
// SICHER: Gerat mit sicherer Firmware-Aktualisierungsfahigkeit
module secure_updateable_device (
input wire clk,
input wire reset_n,
input wire [15:0] addr,
output reg [31:0] data,
output reg device_ready,
// SICHER: Firmware-Update-Schnittstelle
input wire [31:0] update_data,
input wire [15:0] update_addr,
input wire update_write,
input wire update_start,
input wire update_complete,
// Signaturverifizierung
input wire [255:0] update_signature,
input wire verify_signature,
output reg signature_valid,
output reg update_success,
output reg update_error
);
// Firmware in Flash - kann aktualisiert werden
reg [31:0] firmware_flash [0:16383];
// SICHER: Update-Staging-Bereich
reg [31:0] update_buffer [0:16383];
reg [15:0] update_counter;
// SICHER: Offentlicher Schlüssel für Signaturverifizierung (im ROM)
reg [255:0] signing_public_key;
initial begin
signing_public_key = 256'h...; // Offentlicher Schlüssel des Herstellers
end
// Zustandsmaschine für Update-Prozess
reg [2:0] update_state;
parameter IDLE = 3'd0;
parameter RECEIVING = 3'd1;
parameter VERIFYING = 3'd2;
parameter WRITING = 3'd3;
parameter COMPLETE = 3'd4;
parameter ERROR = 3'd5;
always @(posedge clk or negedge reset_n) begin
if (!reset_n) begin
update_state <= IDLE;
update_success <= 1'b0;
update_error <= 1'b0;
signature_valid <= 1'b0;
device_ready <= 1'b0;
end
else begin
case (update_state)
IDLE: begin
update_error <= 1'b0;
device_ready <= 1'b1;
// Normaler Betrieb - aus Flash lesen
data <= firmware_flash[addr];
if (update_start) begin
update_state <= RECEIVING;
update_counter <= 16'h0;
device_ready <= 1'b0;
end
end
RECEIVING: begin
// SICHER: Update in Staging-Buffer empfangen
if (update_write) begin
update_buffer[update_addr] <= update_data;
update_counter <= update_counter + 1;
end
if (update_complete) begin
update_state <= VERIFYING;
end
end
VERIFYING: begin
// SICHER: Signatur vor Anwendung des Updates verifizieren
if (verify_signature) begin
if (verify_ecdsa(update_buffer, update_counter,
update_signature, signing_public_key)) begin
signature_valid <= 1'b1;
update_state <= WRITING;
end
else begin
signature_valid <= 1'b0;
update_state <= ERROR;
end
end
end
WRITING: begin
// SICHER: Verifiziertes Update in Haupt-Flash kopieren
if (update_counter > 0) begin
firmware_flash[16383 - update_counter] <=
update_buffer[16383 - update_counter];
update_counter <= update_counter - 1;
end
else begin
update_state <= COMPLETE;
end
end
COMPLETE: begin
update_success <= 1'b1;
update_state <= IDLE;
// Gerat wird mit neuer Firmware neustarten
end
ERROR: begin
update_error <= 1'b1;
// Staging-Buffer loschen
update_state <= IDLE;
end
endcase
end
end
endmodule
// SICHER: Secure Boot mit Update-Unterstützung
module secure_boot_with_update (
input wire clk,
input wire reset_n,
input wire [31:0] flash_data,
output reg [15:0] flash_addr,
output reg boot_success,
output reg boot_error,
// Update-Bank-Auswahl
input wire use_backup_bank,
output reg active_bank
);
// SICHER: Dual-Bank-Flash für sichere Updates
parameter BANK_A_START = 16'h0000;
parameter BANK_B_START = 16'h8000;
reg [2:0] boot_state;
parameter INIT = 3'd0;
parameter VERIFY_MAIN = 3'd1;
parameter VERIFY_BACKUP = 3'd2;
parameter BOOT = 3'd3;
parameter FALLBACK = 3'd4;
always @(posedge clk or negedge reset_n) begin
if (!reset_n) begin
boot_state <= INIT;
boot_success <= 1'b0;
boot_error <= 1'b0;
end
else begin
case (boot_state)
INIT: begin
// SICHER: Verifizierung der primaren Bank starten
flash_addr <= use_backup_bank ? BANK_B_START : BANK_A_START;
boot_state <= VERIFY_MAIN;
end
VERIFY_MAIN: begin
// SICHER: Primäre Firmware-Signatur verifizieren
if (verify_firmware_signature()) begin
active_bank <= use_backup_bank ? 1'b1 : 1'b0;
boot_state <= BOOT;
end
else begin
// Backup-Bank versuchen
boot_state <= VERIFY_BACKUP;
end
end
VERIFY_BACKUP: begin
// SICHER: Backup-Firmware verifizieren
flash_addr <= use_backup_bank ? BANK_A_START : BANK_B_START;
if (verify_firmware_signature()) begin
active_bank <= use_backup_bank ? 1'b0 : 1'b1;
boot_state <= FALLBACK;
end
else begin
// Beide Banken fehlgeschlagen
boot_error <= 1'b1;
end
end
BOOT: begin
boot_success <= 1'b1;
// Verifizierte Firmware ausführen
end
FALLBACK: begin
// SICHER: Von Backup nach Protokollierung des Fehlers booten
log_boot_failure();
boot_success <= 1'b1;
end
endcase
end
end
endmodule
// SICHER: IoT-Gerat mit sicherer Aktualisierungsfahigkeit
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
// SICHER: Firmware-Aktualisierungsfahigkeit
#define FLASH_BANK_A 0x08000000
#define FLASH_BANK_B 0x08040000
#define FLASH_BANK_SIZE 0x40000
// Offentlicher Schlüssel für Firmware-Verifizierung (im schreibgeschützten Speicher)
static const uint8_t manufacturer_public_key[64] = { /* ... */ };
typedef struct {
uint32_t magic;
uint32_t version;
uint32_t size;
uint8_t signature[64];
uint8_t data[];
} firmware_image_t;
// SICHER: Firmware-Signatur verifizieren
static bool verify_firmware(const firmware_image_t* image) {
// Magische Nummer prüfen
if (image->magic != 0x46575550) { // "FWUP"
return false;
}
// Große ist gültig prüfen
if (image->size > FLASH_BANK_SIZE - sizeof(firmware_image_t)) {
return false;
}
// SICHER: ECDSA-Signatur verifizieren
if (!ecdsa_verify(
manufacturer_public_key,
image->data,
image->size,
image->signature)) {
log_error("Firmware-Signaturverifizierung fehlgeschlagen");
return false;
}
return true;
}
// SICHER: Sicherer Firmware-Aktualisierungsprozess
typedef enum {
UPDATE_SUCCESS,
UPDATE_INVALID_IMAGE,
UPDATE_VERIFICATION_FAILED,
UPDATE_FLASH_ERROR,
UPDATE_ROLLBACK_ATTEMPTED
} update_result_t;
update_result_t secure_firmware_update(const uint8_t* update_data, size_t len) {
const firmware_image_t* image = (const firmware_image_t*)update_data;
// SICHER: Vor Schreiben verifizieren
if (!verify_firmware(image)) {
return UPDATE_VERIFICATION_FAILED;
}
// SICHER: Version prüfen um Rollback zu verhindern
uint32_t current_version = get_current_firmware_version();
if (image->version < current_version) {
log_security_event("Firmware-Rollback-Versuch blockiert");
return UPDATE_ROLLBACK_ATTEMPTED;
}
// SICHER: Inaktive Bank für Update bestimmen
uint32_t target_bank = get_inactive_bank();
uint32_t target_addr = (target_bank == 0) ? FLASH_BANK_A : FLASH_BANK_B;
// SICHER: Zielbank loschen
if (!flash_erase_bank(target_addr, FLASH_BANK_SIZE)) {
return UPDATE_FLASH_ERROR;
}
// SICHER: Neue Firmware schreiben
if (!flash_write(target_addr, update_data, len)) {
return UPDATE_FLASH_ERROR;
}
// SICHER: Geschriebene Daten verifizieren
if (memcmp((void*)target_addr, update_data, len) != 0) {
return UPDATE_FLASH_ERROR;
}
// SICHER: Bank-Auswahl für nächsten Boot aktualisieren
set_active_bank(target_bank);
log_info("Firmware-Update erfolgreich, Version %u -> %u",
current_version, image->version);
return UPDATE_SUCCESS;
}
// SICHER: Hauptschleife mit Aktualisierungsfahigkeit
void secure_device_main(void) {
// Firmware-Integritat beim Boot verifizieren
if (!verify_current_firmware()) {
// Von Backup-Bank booten
boot_backup_firmware();
return;
}
init_hardware();
init_network();
while (1) {
process_sensor_data();
send_to_cloud();
receive_commands();
// SICHER: Firmware-Updates prüfen und anwenden
if (firmware_update_available()) {
uint8_t* update_data;
size_t update_size;
if (download_firmware_update(&update_data, &update_size)) {
update_result_t result = secure_firmware_update(
update_data, update_size);
if (result == UPDATE_SUCCESS) {
// Neustarten um Update anzuwenden
system_reboot();
}
else {
log_error("Firmware-Update fehlgeschlagen: %d", result);
}
free(update_data);
}
}
}
}
// SICHER: Automatische Update-Prüfung
void check_for_updates_periodically(void) {
static uint32_t last_check = 0;
uint32_t now = get_current_time();
// Alle 24 Stunden prüfen
if (now - last_check > 86400) {
last_check = now;
if (check_update_server()) {
schedule_firmware_update();
}
}
}
CVE-Beispiele
- CVE-2020-9054: Network-Attached-Storage-Gerate mit OS-Command-Injection-Schwachstellen wurden aktiv für Botnet-Rekrutierung ausgenutzt, aber End-of-Support-Produkte können nicht gepatcht werden.
- Smart Lock mit schwacher Schlüsselerzeugungsschwachstelle über Bluetooth-Sniffing erkennbar - Firmware kann nicht aktualisiert werden.
Verwandte CWEs
- CWE-1329: Abhängigkeit von nicht aktualisierbarer Komponente (ubergeordnet)
- CWE-1208: Querschnittsprobleme (Kategorie)
- CWE-912: Versteckte Funktionalitat (verwandt)
- CAPEC-682: Ausnutzung von Firmware oder ROM-Code mit nicht patchbaren Schwachstellen (Angriffsmuster)
Referenzen
- MITRE Corporation. "CWE-1277: Firmware Not Updateable." https://cwe.mitre.org/data/definitions/1277.html
- NIST. "Guidelines for Firmware Update"
- IEC 62443. "Industrial Cybersecurity Standards"