Unzureichende Granularität von durch Register-Sperren geschützten Adressbereichen
Beschreibung
Unzureichende Granularität von durch Register-Sperren geschützten Adressbereichen tritt auf, wenn ein Hardware-Design Adressbereiche mit Register-Sperren schützt, aber mit unzureichender Granularität, was eine unautorisierte Modifikation geschützten Speichers ermöglicht. Sicherheitsmaßnahmen wie Sperren werden häufig implementiert, um unautorisierten Zugriff auf geschützte Speicherbereiche zu verhindern. Wenn die Granularität dieser Sperren jedoch größer als nötig ist -- breitere Bereiche als beabsichtigt schützend -- werden Teile des Speichers gesperrt, die modifizierbar bleiben sollten, während unzureichende Abdeckung Lücken hinterlässt. Angreifer können diese Lücken ausnutzen, um vermeintlich geschützte Daten zu modifizieren.
Risiko
Unzureichende Adressschutz-Granularität hat schwerwiegende Sicherheitsauswirkungen. Geschützte Daten können durch Lücken in der Abdeckung zugänglich sein. Kritische Konfiguration kann außerhalb gesperrter Bereiche modifizierbar sein. Sicherheitsgrenzen können nicht präzise durchgesetzt werden. Boot-Code-Schutz kann ausnutzbare Lücken haben. Firmware-Integrität kann kompromittiert werden. Schlüsselspeicherbereiche können teilweise exponiert sein. Zugriffskontrollrichtlinien können umgangen werden. Sensible Daten können durch ungeschützte angrenzende Bereiche durchsickern.
Lösung
Implementieren Sie Sperrmechanismen mit einer Granularität, die den Schutzanforderungen entspricht. Verwenden Sie mehrere Sperrbereiche, um nicht zusammenhängende geschützte Bereiche abzudecken. Stellen Sie sicher, dass keine Lücken zwischen geschützten Bereichen bestehen. Überprüfen Sie die Sperrabdeckung durch Sicherheitstests. Dokumentieren Sie genau, welche Adressen durch jede Sperre geschützt sind. Erwägen Sie Seitenlevel- oder Cache-Line-Level-Sperrung. Implementieren Sie Hardware-Überprüfung der Sperrabdeckung. Testen Sie Grenzbedingungen um geschützte Bereiche. Verwenden Sie Defense in Depth mit überlappenden Schutzmechanismen.
Häufige Auswirkungen
| Auswirkung | Details |
|---|---|
| Integrität | Bereich: Integrität Speicher modifizieren – Angreifer können geschützten Speicher durch Lücken in der Sperrabdeckung oder durch Ausnutzung grober Granularität modifizieren. |
| Zugriffskontrolle | Bereich: Zugriffskontrolle Umgehung von Schutzmechanismen – Unzureichende Granularität ermöglicht die Umgehung des durch Sperren beabsichtigten Speicherschutzes. |
Beispielcode und Lösung
Verwundbarer Code
// VERWUNDBAR: Grobkörniger Speichersperrschutz
module vulnerable_memory_lock (
input wire clk,
input wire reset_n,
input wire [31:0] address,
input wire [31:0] write_data,
input wire write_enable,
input wire set_lock,
output reg [31:0] read_data,
output reg write_error
);
// Speicher-Array
reg [31:0] memory [0:4095]; // 16KB Speicher
// VERWUNDBAR: Einzelne Sperre für gesamten Speicher
// Kann spezifische Bereiche nicht unabhängig schützen
reg memory_locked;
always @(posedge clk or negedge reset_n) begin
if (!reset_n) begin
memory_locked <= 1'b0;
end
else if (set_lock) begin
memory_locked <= 1'b1; // Sperrt GESAMTEN Speicher
end
end
always @(posedge clk) begin
if (write_enable) begin
if (memory_locked) begin
// VERWUNDBAR: Alles gesperrt – zu grob
// Oder nichts gesperrt – kein Schutz
write_error <= 1'b1;
end else begin
memory[address[13:2]] <= write_data;
write_error <= 1'b0;
end
end
end
endmodule
// VERWUNDBAR: Sperrbereiche mit Lücken
module vulnerable_region_locks (
input wire clk,
input wire [31:0] address,
input wire [31:0] write_data,
input wire write_enable,
output reg write_error
);
// Speicherbereiche
// 0x0000-0x0FFF: Boot-Code (sollte geschützt sein)
// 0x1000-0x1FFF: Konfiguration (sollte geschützt sein)
// 0x2000-0x2FFF: Schlüsselspeicher (sollte geschützt sein)
// 0x3000-0x3FFF: Benutzerdaten (beschreibbar)
// VERWUNDBAR: Sperrbereiche stimmen nicht mit Datengrenzen überein
reg lock_region_0; // Deckt 0x0000-0x07FF ab (nur Hälfte des Boot-Codes!)
reg lock_region_1; // Deckt 0x0800-0x0FFF ab
reg lock_region_2; // Deckt 0x1000-0x17FF ab
// LÜCKE: 0x1800-0x1FFF von keiner Sperre abgedeckt!
reg lock_region_3; // Deckt 0x2000-0x2FFF ab
always @(*) begin
write_error = 1'b0;
if (address < 32'h0800) begin
if (lock_region_0) write_error = 1'b1;
end
else if (address < 32'h1000) begin
if (lock_region_1) write_error = 1'b1;
end
else if (address < 32'h1800) begin
if (lock_region_2) write_error = 1'b1;
end
// LÜCKE: 0x1800-0x1FFF hat KEINEN Sperrschutz!
// Angreifer kann diesen Bereich modifizieren
else if (address >= 32'h2000 && address < 32'h3000) begin
if (lock_region_3) write_error = 1'b1;
end
end
endmodule
// VERWUNDBAR: Software ohne Bewusstsein für unzureichende Sperrgranularität
#define BOOT_CODE_START 0x0000
#define BOOT_CODE_END 0x0FFF
#define CONFIG_START 0x1000
#define CONFIG_END 0x1FFF
#define KEY_STORAGE_START 0x2000
#define KEY_STORAGE_END 0x2FFF
// Hardware-Sperrbereiche (nicht mit Daten ausgerichtet)
#define LOCK_REGION_SIZE 0x0800 // 2KB pro Sperre
void vulnerable_setup_locks(void) {
// VERWUNDBAR: Sperren decken beabsichtigte Bereiche nicht korrekt ab
// Dies sperrt nur die Hälfte des Boot-Codes
set_lock_region(0); // Deckt 0x0000-0x07FF ab
set_lock_region(1); // Deckt 0x0800-0x0FFF ab
// Dies sperrt nur die Hälfte der Konfiguration
set_lock_region(2); // Deckt 0x1000-0x17FF ab
// Bereich 0x1800-0x1FFF ist NICHT GESPERRT!
set_lock_region(3); // Deckt 0x2000-0x27FF ab
// Schlüsselspeicher 0x2800-0x2FFF ist NICHT GESPERRT!
}
// Angreifer kann Lücken ausnutzen
void exploit_lock_gap(void) {
// Konfigurationsbereich ist "gesperrt" aber...
// Adresse 0x1800-0x1FFF hat keine Sperre!
uint32_t* config_gap = (uint32_t*)0x1800;
*config_gap = MALICIOUS_CONFIG; // Funktioniert! Keine Sperre hier
// Schlüsselspeicher ist "gesperrt" aber...
// Adresse 0x2800-0x2FFF hat keine Sperre!
uint32_t* key_gap = (uint32_t*)0x2800;
*key_gap = 0; // Kann Schlüssel beschädigen!
}
Sichere Lösung
// SICHER: Feinkörniger Speichersperrschutz
module secure_memory_lock (
input wire clk,
input wire reset_n,
input wire [31:0] address,
input wire [31:0] write_data,
input wire write_enable,
input wire [15:0] set_lock_mask,
input wire lock_enable,
output reg [31:0] read_data,
output reg write_error
);
// Speicher-Array
reg [31:0] memory [0:4095]; // 16KB Speicher
// Feinkörnige Sperren: eine pro 1KB-Bereich
reg [15:0] region_locks; // 16 Sperren für 16KB
// Bereichsgröße in Bytes
localparam REGION_SIZE = 1024; // 1KB pro Sperrbereich
localparam REGION_BITS = 10;
wire [3:0] region_index = address[13:REGION_BITS];
always @(posedge clk or negedge reset_n) begin
if (!reset_n) begin
region_locks <= 16'h0;
end
else if (lock_enable) begin
// Kann mehrere Bereiche atomar sperren
region_locks <= region_locks | set_lock_mask;
end
end
always @(posedge clk) begin
if (write_enable) begin
// Spezifische Bereichssperre prüfen
if (region_locks[region_index]) begin
write_error <= 1'b1;
end else begin
memory[address[13:2]] <= write_data;
write_error <= 1'b0;
end
end
end
endmodule
// SICHER: Konfigurierbare Sperrbereiche mit vollständiger Abdeckung
module secure_region_locks (
input wire clk,
input wire reset_n,
input wire [31:0] address,
input wire [31:0] write_data,
input wire write_enable,
input wire configure_enable,
input wire [3:0] region_select,
input wire [31:0] region_start_in,
input wire [31:0] region_end_in,
input wire lock_region,
output reg write_error
);
// Konfigurierbare geschützte Bereiche
parameter NUM_REGIONS = 8;
reg [31:0] region_start [0:NUM_REGIONS-1];
reg [31:0] region_end [0:NUM_REGIONS-1];
reg [NUM_REGIONS-1:0] region_locked;
reg configuration_locked;
integer i;
// Prüfen ob Adresse in einem gesperrten Bereich liegt
function is_address_locked;
input [31:0] addr;
integer j;
begin
is_address_locked = 1'b0;
for (j = 0; j < NUM_REGIONS; j = j + 1) begin
if (region_locked[j] &&
addr >= region_start[j] &&
addr <= region_end[j]) begin
is_address_locked = 1'b1;
end
end
end
endfunction
always @(posedge clk or negedge reset_n) begin
if (!reset_n) begin
for (i = 0; i < NUM_REGIONS; i = i + 1) begin
region_start[i] <= 32'hFFFFFFFF;
region_end[i] <= 32'h00000000;
region_locked[i] <= 1'b0;
end
configuration_locked <= 1'b0;
end
else if (configure_enable && !configuration_locked) begin
// Bereichsgrenzen konfigurieren
region_start[region_select] <= region_start_in;
region_end[region_select] <= region_end_in;
if (lock_region) begin
region_locked[region_select] <= 1'b1;
end
end
end
always @(*) begin
write_error = is_address_locked(address);
end
endmodule
// SICHER: Hierarchisches Sperrsystem mit garantierter Abdeckung
module secure_hierarchical_locks (
input wire clk,
input wire reset_n,
input wire [31:0] address,
input wire write_enable,
output reg write_error
);
// Hierarchische Sperren für vollständige Abdeckung
// Ebene 0: Grob (4KB-Bereiche)
// Ebene 1: Mittel (1KB-Bereiche)
// Ebene 2: Fein (256B-Bereiche)
reg [3:0] coarse_locks; // 4 x 4KB = 16KB
reg [15:0] medium_locks; // 16 x 1KB = 16KB
reg [63:0] fine_locks; // 64 x 256B = 16KB
wire [1:0] coarse_index = address[13:12];
wire [3:0] medium_index = address[13:10];
wire [5:0] fine_index = address[13:8];
// Adresse ist gesperrt wenn IRGENDEINE Ebene sie sperrt
wire coarse_locked = coarse_locks[coarse_index];
wire medium_locked = medium_locks[medium_index];
wire fine_locked = fine_locks[fine_index];
always @(*) begin
// Hierarchische Prüfung - jede Sperre blockiert Zugriff
write_error = coarse_locked | medium_locked | fine_locked;
end
endmodule
// SICHER: Software mit korrekter Sperrgranularität
#define BOOT_CODE_START 0x0000
#define BOOT_CODE_END 0x0FFF
#define CONFIG_START 0x1000
#define CONFIG_END 0x1FFF
#define KEY_STORAGE_START 0x2000
#define KEY_STORAGE_END 0x2FFF
// Feinkörnige Sperrkontrolle
#define LOCK_REGION_SIZE 0x0400 // 1KB pro Sperre – passt zu Datengrenzen
void secure_setup_locks(void) {
// Sperren so konfigurieren, dass sie genau zu geschützten Bereichen passen
// Boot-Code: 0x0000-0x0FFF (4 Sperrbereiche)
configure_lock_region(0, BOOT_CODE_START, BOOT_CODE_START + 0x3FF);
configure_lock_region(1, BOOT_CODE_START + 0x400, BOOT_CODE_START + 0x7FF);
configure_lock_region(2, BOOT_CODE_START + 0x800, BOOT_CODE_START + 0xBFF);
configure_lock_region(3, BOOT_CODE_START + 0xC00, BOOT_CODE_END);
// Konfiguration: 0x1000-0x1FFF (4 Sperrbereiche)
configure_lock_region(4, CONFIG_START, CONFIG_START + 0x3FF);
configure_lock_region(5, CONFIG_START + 0x400, CONFIG_START + 0x7FF);
configure_lock_region(6, CONFIG_START + 0x800, CONFIG_START + 0xBFF);
configure_lock_region(7, CONFIG_START + 0xC00, CONFIG_END);
// Schlüsselspeicher: 0x2000-0x2FFF (4 Sperrbereiche)
configure_lock_region(8, KEY_STORAGE_START, KEY_STORAGE_START + 0x3FF);
configure_lock_region(9, KEY_STORAGE_START + 0x400, KEY_STORAGE_START + 0x7FF);
configure_lock_region(10, KEY_STORAGE_START + 0x800, KEY_STORAGE_START + 0xBFF);
configure_lock_region(11, KEY_STORAGE_START + 0xC00, KEY_STORAGE_END);
// Alle konfigurierten Sperren aktivieren
for (int i = 0; i <= 11; i++) {
activate_lock_region(i);
}
// Vollständige Abdeckung überprüfen
verify_lock_coverage();
}
// Überprüfungsfunktion
bool verify_lock_coverage(void) {
// Prüfen, dass alle geschützten Bereiche vollständig abgedeckt sind
for (uint32_t addr = BOOT_CODE_START; addr <= BOOT_CODE_END; addr += 4) {
if (!is_address_locked(addr)) {
log_error("Boot-Code-Lücke bei 0x%08X", addr);
return false;
}
}
for (uint32_t addr = CONFIG_START; addr <= CONFIG_END; addr += 4) {
if (!is_address_locked(addr)) {
log_error("Konfigurations-Lücke bei 0x%08X", addr);
return false;
}
}
for (uint32_t addr = KEY_STORAGE_START; addr <= KEY_STORAGE_END; addr += 4) {
if (!is_address_locked(addr)) {
log_error("Schlüsselspeicher-Lücke bei 0x%08X", addr);
return false;
}
}
// Überprüfen, dass Benutzerbereich NICHT gesperrt ist
for (uint32_t addr = 0x3000; addr <= 0x3FFF; addr += 4) {
if (is_address_locked(addr)) {
log_error("Benutzerbereich fälschlicherweise gesperrt bei 0x%08X", addr);
return false;
}
}
return true;
}
CVE-Beispiele
Probleme mit der Granularität von Adressbereichssperren wurden in verschiedenen Hardware-Designs gefunden, bei denen geschützte Bereiche Lücken oder nicht ausgerichtete Grenzen hatten.
Verwandte CWEs
- CWE-1220: Insufficient Granularity of Access Control (verwandt)
- CWE-1222: Insufficient Granularity of Address Regions (übergeordnetes Konzept)
- CWE-1198: Privilege Separation and Access Control Issues (Kategoriemitglied)
Referenzen
- MITRE Corporation. "CWE-1222: Insufficient Granularity of Address Regions Protected by Register Locks." https://cwe.mitre.org/data/definitions/1222.html
- Richtlinien zum Design von Memory Protection Units
- Best Practices für Hardware-Sperr-Implementierung