Unsachgemäße Zugriffskontrolle für Registerschnittstelle
Beschreibung
Unsachgemäße Zugriffskontrolle für Registerschnittstelle tritt auf, wenn ein Produkt speicherabgebildete I/O-Register verwendet, die Hardware-Zugriff von Software ermöglichen, aber keine ordnungsgemäßen Zugriffskontrollen für diese Register hat. Peripheriegeräte in Systems-on-Chip (SoC) und anderen Geräten werden üblicherweise über speicherabgebildete Registerschnittstellen angesprochen. Ohne angemessenen Schutz könnte bösartige Software sicherheitskritische Hardware-Daten kompromittieren, was zu Verlust von Vertraulichkeit und Integrität führt.
Risiko
Ungeschützte Registerschnittstellen haben schwerwiegende Sicherheitsauswirkungen. Kryptographische Schlüssel können lesbar sein. Sicherheitskonfigurationen können modifiziert werden. Hardware-Zustand kann korrumpiert werden. Schutzmechanismen können umgangen werden. Privilegieneskalation wird möglich. Sicherheitskritische Daten können verändert werden. Unerwartete Hardware-Zustände können ausgelöst werden. Ausführungslogik kann böswillig modifiziert werden.
Lösung
Etablieren Sie ordnungsgemäße Richtlinien für Hardware-Registerzugriff von Software. Stellen Sie sicher, dass Zugriffskontrollrichtlinien gemäß Spezifikationen korrekt implementiert werden. Implementieren Sie Privilegstufen-Prüfungen für Registerzugriff. Deaktivieren Sie Rücklese-Pfade für sensible Daten wie kryptographische Schlüssel. Verwenden Sie hardware-erzwungene Zugriffskontrolle. Validieren Sie alle Registeradressen und -werte. Implementieren Sie ordnungsgemäßen CSR-Schutz in Prozessoren.
Häufige Auswirkungen
| Auswirkung | Details |
|---|---|
| Vertraulichkeit | Bereich: Vertraulichkeit Speicher lesen - Angreifer können geschützte Informationen durch ungeschützte Register lesen. |
| Integrität | Bereich: Integrität Speicher modifizieren - Sicherheitszustand, Einstellungen und kritische Daten können korrumpiert oder modifiziert werden. |
| Zugriffskontrolle | Bereich: Zugriffskontrolle Privilegien erlangen - Unautorisierte Privilegieneskalation durch Registermanipulation. |
Beispielcode und Lösung
Verwundbarer Code
// VERWUNDBAR: Kryptographischer Beschleuniger mit lesbaren Schlüsseln
module vulnerable_crypto_accelerator (
input wire clk,
input wire reset_n,
input wire [7:0] reg_addr,
input wire [31:0] reg_write_data,
input wire reg_write,
input wire reg_read,
output reg [31:0] reg_read_data
);
// Schlüsselspeicher
reg [255:0] crypto_key;
// Status- und Kontrollregister
reg [31:0] status_reg;
reg [31:0] control_reg;
// Registeradressen
parameter KEY_REG_0 = 8'h00;
parameter KEY_REG_1 = 8'h04;
parameter KEY_REG_2 = 8'h08;
parameter KEY_REG_3 = 8'h0C;
parameter KEY_REG_4 = 8'h10;
parameter KEY_REG_5 = 8'h14;
parameter KEY_REG_6 = 8'h18;
parameter KEY_REG_7 = 8'h1C;
parameter STATUS_REG = 8'h20;
parameter CONTROL_REG = 8'h24;
// Schlüssel schreiben
always @(posedge clk or negedge reset_n) begin
if (!reset_n) begin
crypto_key <= 256'h0;
end
else if (reg_write) begin
case (reg_addr)
KEY_REG_0: crypto_key[31:0] <= reg_write_data;
KEY_REG_1: crypto_key[63:32] <= reg_write_data;
KEY_REG_2: crypto_key[95:64] <= reg_write_data;
KEY_REG_3: crypto_key[127:96] <= reg_write_data;
KEY_REG_4: crypto_key[159:128] <= reg_write_data;
KEY_REG_5: crypto_key[191:160] <= reg_write_data;
KEY_REG_6: crypto_key[223:192] <= reg_write_data;
KEY_REG_7: crypto_key[255:224] <= reg_write_data;
CONTROL_REG: control_reg <= reg_write_data;
endcase
end
end
// VERWUNDBAR: Schlüsselregister sind lesbar!
always @(*) begin
case (reg_addr)
// VERWUNDBAR: Schlüssel kann von jeder Software zurückgelesen werden
KEY_REG_0: reg_read_data = crypto_key[31:0];
KEY_REG_1: reg_read_data = crypto_key[63:32];
KEY_REG_2: reg_read_data = crypto_key[95:64];
KEY_REG_3: reg_read_data = crypto_key[127:96];
KEY_REG_4: reg_read_data = crypto_key[159:128];
KEY_REG_5: reg_read_data = crypto_key[191:160];
KEY_REG_6: reg_read_data = crypto_key[223:192];
KEY_REG_7: reg_read_data = crypto_key[255:224];
STATUS_REG: reg_read_data = status_reg;
CONTROL_REG: reg_read_data = control_reg;
default: reg_read_data = 32'h0;
endcase
end
endmodule
// VERWUNDBAR: RISC-V CSR ohne ordnungsgemäße Privilegprüfung
module vulnerable_csr_module (
input wire clk,
input wire reset_n,
input wire [11:0] csr_addr,
input wire [31:0] csr_write_data,
input wire csr_write,
input wire csr_read,
input wire [1:0] privilege_level, // 0=U, 1=S, 3=M
output reg [31:0] csr_read_data,
output reg illegal_access
);
// Machine-Level CSRs (erfordern M-Modus)
reg [31:0] mstatus;
reg [31:0] mepc;
reg [31:0] mcause;
reg [31:0] mtvec;
// CSR-Adressen
parameter MSTATUS = 12'h300;
parameter MEPC = 12'h341;
parameter MCAUSE = 12'h342;
parameter MTVEC = 12'h305;
always @(posedge clk or negedge reset_n) begin
if (!reset_n) begin
mstatus <= 32'h0;
mepc <= 32'h0;
mcause <= 32'h0;
mtvec <= 32'h0;
illegal_access <= 1'b0;
end
else if (csr_write) begin
// VERWUNDBAR: MEPC von Privilegprüfung ausgeschlossen!
if (csr_addr == MEPC) begin
// VERWUNDBAR: Jede Privilegstufe kann MEPC schreiben
mepc <= csr_write_data;
end
// Andere CSRs ordnungsgemäß geschützt
else if (csr_addr[11:10] == 2'b11 && privilege_level != 2'd3) begin
illegal_access <= 1'b1;
end
else begin
case (csr_addr)
MSTATUS: mstatus <= csr_write_data;
MCAUSE: mcause <= csr_write_data;
MTVEC: mtvec <= csr_write_data;
endcase
end
end
end
// Angriff: Benutzermodus schreibt MEPC, um Exception-Rücksprung
// auf beliebigen Code umzuleiten und Privilegieneskalation zu erreichen
endmodule
// VERWUNDBAR: Software greift auf ungeschützte Register zu
#include <stdint.h>
#define CRYPTO_BASE 0x40000000
#define CRYPTO_KEY_REG_0 (CRYPTO_BASE + 0x00)
#define CRYPTO_KEY_REG_1 (CRYPTO_BASE + 0x04)
// ...
// VERWUNDBAR: Jeder Prozess kann den Schlüssel lesen
void vulnerable_read_key(uint8_t* key_buffer) {
volatile uint32_t* key_regs = (volatile uint32_t*)CRYPTO_KEY_REG_0;
// VERWUNDBAR: Keine Zugriffskontrollprüfung
// Bösartiger Prozess kann kryptographischen Schlüssel lesen
for (int i = 0; i < 8; i++) {
((uint32_t*)key_buffer)[i] = key_regs[i];
}
}
// VERWUNDBAR: Jeder Prozess kann Sicherheitsregister modifizieren
void vulnerable_modify_security_config(void) {
volatile uint32_t* security_ctrl = (volatile uint32_t*)0x40001000;
// VERWUNDBAR: Keine Privilegprüfung
*security_ctrl = 0; // Sicherheitsfunktionen deaktivieren
}
Sichere Lösung
// SICHER: Kryptographischer Beschleuniger mit geschützten Schlüsseln
module secure_crypto_accelerator (
input wire clk,
input wire reset_n,
input wire [7:0] reg_addr,
input wire [31:0] reg_write_data,
input wire reg_write,
input wire reg_read,
input wire [1:0] privilege_level, // 0=Benutzer, 1=Supervisor, 2=Hypervisor, 3=sicher
input wire secure_access, // Hardware-erzwungenes Sicher-Zugriffssignal
output reg [31:0] reg_read_data,
output reg access_denied
);
// Schlüsselspeicher
reg [255:0] crypto_key;
reg key_loaded;
// Status- und Kontrollregister
reg [31:0] status_reg;
reg [31:0] control_reg;
// Registeradressen
parameter KEY_REG_0 = 8'h00;
parameter KEY_REG_1 = 8'h04;
parameter KEY_REG_2 = 8'h08;
parameter KEY_REG_3 = 8'h0C;
parameter KEY_REG_4 = 8'h10;
parameter KEY_REG_5 = 8'h14;
parameter KEY_REG_6 = 8'h18;
parameter KEY_REG_7 = 8'h1C;
parameter STATUS_REG = 8'h20;
parameter CONTROL_REG = 8'h24;
// SICHER: Schlüsseladressen sind nur-schreiben, erfordern sicheren Zugriff
wire is_key_addr = (reg_addr >= KEY_REG_0) && (reg_addr <= KEY_REG_7);
always @(posedge clk or negedge reset_n) begin
if (!reset_n) begin
crypto_key <= 256'h0;
key_loaded <= 1'b0;
access_denied <= 1'b0;
end
else begin
access_denied <= 1'b0;
if (reg_write) begin
// SICHER: Schlüsselschreibvorgänge erfordern sicheren Zugriff
if (is_key_addr) begin
if (!secure_access) begin
access_denied <= 1'b1;
end
else begin
case (reg_addr)
KEY_REG_0: crypto_key[31:0] <= reg_write_data;
KEY_REG_1: crypto_key[63:32] <= reg_write_data;
KEY_REG_2: crypto_key[95:64] <= reg_write_data;
KEY_REG_3: crypto_key[127:96] <= reg_write_data;
KEY_REG_4: crypto_key[159:128] <= reg_write_data;
KEY_REG_5: crypto_key[191:160] <= reg_write_data;
KEY_REG_6: crypto_key[223:192] <= reg_write_data;
KEY_REG_7: begin
crypto_key[255:224] <= reg_write_data;
key_loaded <= 1'b1;
end
endcase
end
end
// Kontrollregister erfordert mindestens Supervisor
else if (reg_addr == CONTROL_REG) begin
if (privilege_level < 2'd1) begin
access_denied <= 1'b1;
end
else begin
control_reg <= reg_write_data;
end
end
end
end
end
// SICHER: Schlüsselregister sind NICHT lesbar
always @(*) begin
access_denied = 1'b0;
if (reg_read) begin
case (reg_addr)
// SICHER: Schlüsselregister geben Null zurück, nicht echten Schlüssel
KEY_REG_0, KEY_REG_1, KEY_REG_2, KEY_REG_3,
KEY_REG_4, KEY_REG_5, KEY_REG_6, KEY_REG_7: begin
reg_read_data = 32'h0; // Nur-schreiben
access_denied = 1'b1; // Zugriffsversuch markieren
end
STATUS_REG: reg_read_data = status_reg;
CONTROL_REG: begin
if (privilege_level < 2'd1) begin
reg_read_data = 32'h0;
access_denied = 1'b1;
end
else begin
reg_read_data = control_reg;
end
end
default: reg_read_data = 32'h0;
endcase
end
else begin
reg_read_data = 32'h0;
end
end
endmodule
// SICHER: RISC-V CSR mit ordnungsgemäßer Privilegprüfung
module secure_csr_module (
input wire clk,
input wire reset_n,
input wire [11:0] csr_addr,
input wire [31:0] csr_write_data,
input wire csr_write,
input wire csr_read,
input wire [1:0] privilege_level,
output reg [31:0] csr_read_data,
output reg illegal_access
);
// Machine-Level CSRs
reg [31:0] mstatus;
reg [31:0] mepc;
reg [31:0] mcause;
reg [31:0] mtvec;
parameter MSTATUS = 12'h300;
parameter MEPC = 12'h341;
parameter MCAUSE = 12'h342;
parameter MTVEC = 12'h305;
// SICHER: Erforderliches Privileg aus CSR-Adresse extrahieren
wire [1:0] required_privilege = csr_addr[9:8];
// SICHER: Alle M-Modus-CSRs erfordern M-Modus-Privileg
wire privilege_sufficient = (privilege_level >= required_privilege);
always @(posedge clk or negedge reset_n) begin
if (!reset_n) begin
mstatus <= 32'h0;
mepc <= 32'h0;
mcause <= 32'h0;
mtvec <= 32'h0;
illegal_access <= 1'b0;
end
else begin
illegal_access <= 1'b0;
if (csr_write) begin
// SICHER: Privileg für ALLE CSRs einschließlich MEPC prüfen
if (!privilege_sufficient) begin
illegal_access <= 1'b1;
end
else begin
case (csr_addr)
MSTATUS: mstatus <= csr_write_data;
MEPC: mepc <= csr_write_data; // SICHER: Jetzt geschützt
MCAUSE: mcause <= csr_write_data;
MTVEC: mtvec <= csr_write_data;
default: illegal_access <= 1'b1;
endcase
end
end
if (csr_read) begin
if (!privilege_sufficient) begin
illegal_access <= 1'b1;
csr_read_data <= 32'h0;
end
else begin
case (csr_addr)
MSTATUS: csr_read_data <= mstatus;
MEPC: csr_read_data <= mepc;
MCAUSE: csr_read_data <= mcause;
MTVEC: csr_read_data <= mtvec;
default: csr_read_data <= 32'h0;
endcase
end
end
end
end
endmodule
// SICHER: Software mit ordnungsgemäßer Registerzugriffskontrolle
#include <stdint.h>
#define CRYPTO_BASE 0x40000000
// SICHER: Schlüssel-Laden nur über sichere API
int secure_load_key(const uint8_t* key, size_t key_len) {
// SICHER: Aufrufer-Privileg prüfen
if (get_current_privilege() < PRIVILEGE_SECURE) {
log_security_event("Unprivilegierter Schlüssel-Ladeversuch");
return -EPERM;
}
// SICHER: Schlüssellänge validieren
if (key_len != 32) {
return -EINVAL;
}
// SICHER: Sicheren Hardware-Pfad verwenden
volatile uint32_t* key_regs = (volatile uint32_t*)(CRYPTO_BASE + 0x00);
// Interrupts während Schlüssel-Laden deaktivieren
uint32_t irq_state = disable_interrupts();
for (int i = 0; i < 8; i++) {
key_regs[i] = ((uint32_t*)key)[i];
}
// Speicherbarriere
__sync_synchronize();
restore_interrupts(irq_state);
return 0;
}
// SICHER: Schlüssel-Lesen gibt Fehler zurück
int secure_read_key(uint8_t* key_buffer) {
// SICHER: Schlüssel sind niemals lesbar
log_security_event("Versuch, kryptographischen Schlüssel zu lesen");
return -EPERM;
}
// SICHER: Sicherheitskonfiguration erfordert Privileg
int secure_modify_security_config(uint32_t config) {
if (get_current_privilege() < PRIVILEGE_KERNEL) {
return -EPERM;
}
// Konfigurationswert validieren
if (!is_valid_security_config(config)) {
return -EINVAL;
}
volatile uint32_t* security_ctrl = (volatile uint32_t*)0x40001000;
*security_ctrl = config;
return 0;
}
CVE-Beispiele
- RISC-V-Prozessorimplementierungen, bei denen das MEPC-CSR fälschlicherweise von Privilegprüfungen ausgeschlossen wurde, was Privilegieneskalation im Benutzermodus ermöglichte
- Verschiedene SoC-Schwachstellen, bei denen kryptographische Schlüsselregister von unprivilegierter Software gelesen werden könnten
Verwandte CWEs
- CWE-284: Unsachgemäße Zugriffskontrolle (Eltern)
- CWE-1220: Unzureichende Granularität der Zugriffskontrolle (verwandt)
- CAPEC-680: Ausnutzung unsachgemäß kontrollierter Register (Angriffsmuster)
Referenzen
- MITRE Corporation. "CWE-1262: Improper Access Control for Register Interface." https://cwe.mitre.org/data/definitions/1262.html
- RISC-V. "Privileged Architecture Specification"
- ARM. "TrustZone Security Technology"