Unzureichende Granularität der Zugriffskontrolle
Beschreibung
Unzureichende Granularität der Zugriffskontrolle tritt auf, wenn ein Produkt keine ausreichend feinkörnige Zugriffskontrolle implementiert, die es ermöglichen würde, verschiedene Benutzer, Prozesse oder Agenten basierend auf dem Prinzip der geringsten Rechte selektiv einzuschränken. Grob gekörnter Zugriff gewährt Alles-oder-Nichts-Berechtigungen und zwingt dazu, vollständigen Zugriff zu gewähren, obwohl nur eingeschränkter Zugriff benötigt wird. Dies verstößt gegen das Prinzip der geringsten Rechte und erweitert die Angriffsfläche.
Risiko
Grob gekörnter Zugriff schafft erhebliche Sicherheitsrisiken. Übermäßige Berechtigungen vergrößern die Angriffsfläche. Kompromittierte Komponenten haben breiteren Zugriff. Privilegieneskalation wird einfacher. Datenlecks sind wahrscheinlicher. Sicherheitsisolation ist unwirksam. Die Einhaltung des Prinzips der geringsten Rechte ist unmöglich. Laterale Bewegung nach einem Einbruch ist einfacher.
Lösung
Implementieren Sie Zugriffskontrolle mit ausreichender Granularität, um verschiedenen Entitäten unterschiedliche Berechtigungen zuzuweisen. Definieren Sie separate Berechtigungen für Lesen, Schreiben und Ausführen. Erstellen Sie unterschiedliche Zugriffsebenen für verschiedene Ressourcen. Implementieren Sie rollenbasierte Zugriffskontrolle mit feinkörnigen Rollen. Wenden Sie das Prinzip der geringsten Rechte konsequent an. Überprüfen und minimieren Sie regelmäßig die Berechtigungen.
Häufige Auswirkungen
| Auswirkung | Details |
|---|---|
| Vertraulichkeit | Bereich: Vertraulichkeit Unautorisiertes Lesen - Grob gekörnter Zugriff kann mehr Daten offenlegen als notwendig. |
| Integrität | Bereich: Integrität Unautorisierte Modifikation - Übermäßige Schreibberechtigungen ermöglichen unbeabsichtigte Änderungen. |
| Zugriffskontrolle | Bereich: Zugriffskontrolle Prinzip der geringsten Rechte verletzt - Entitäten haben mehr Berechtigungen als erforderlich. |
Beispielcode und Lösung
Verwundbarer Code
// Verwundbar: Registerschutz ohne Bit-Level-Granularität
module vulnerable_register_access (
input wire clk,
input wire reset_n,
input wire [31:0] write_data,
input wire write_enable,
input wire [3:0] register_select,
input wire privileged_access,
output reg [31:0] read_data
);
// Steuerregister-Layout:
// [0] - Feature aktivieren (benutzerzugänglich)
// [1] - Debug-Modus (sollte geschützt sein!)
// [7:2] - Konfiguration (benutzerzugänglich)
// [8] - Sicherheitsumgehung (sollte geschützt sein!)
// [15:9] - Weitere Konfiguration (benutzerzugänglich)
// [31:16] - Reserviert
reg [31:0] control_register;
reg register_locked;
always @(posedge clk or negedge reset_n) begin
if (!reset_n) begin
control_register <= 32'h0;
register_locked <= 1'b0;
end
else if (write_enable && register_select == 4'b0001) begin
// VERWUNDBAR: Alles-oder-nichts-Schutz
// Entweder ist das gesamte Register beschreibbar oder nicht
if (!register_locked) begin
// Benutzer kann ALLE Bits beschreiben, einschließlich sicherheitskritischer
control_register <= write_data;
end
// Wenn gesperrt, können KEINE Bits geschrieben werden - zu restriktiv
end
end
// Keine Bit-Level-Zugriffskontrolle
// Sensible Bits gemischt mit benutzerzugänglichen Bits
endmodule
// Verwundbar: Gemeinsames Register mit gemischten Sensitivitätsstufen
module vulnerable_mixed_register (
input wire clk,
input wire [31:0] write_data,
input wire write_enable,
input wire user_access,
output reg [31:0] config_register
);
// Gemischtes Register:
// [3:0] - Benutzerkonfiguration
// [4] - Rechteeskalations-Bit (KRITISCH!)
// [7:5] - Benutzereinstellungen
// [8] - Sicherheitsprüfungen deaktivieren (KRITISCH!)
// [31:9] - Benutzerdaten
always @(posedge clk) begin
if (write_enable) begin
// VERWUNDBAR: Keine Unterscheidung zwischen Benutzer- und kritischen Bits
if (user_access) begin
// Benutzer kann alles schreiben, einschließlich kritischer Sicherheitsbits!
config_register <= write_data;
end
end
end
endmodule
// Verwundbar: Firmware mit grober Zugriffskontrolle
#define CONFIG_REG_ADDR 0x40001000
// Registerbits (gemischte Sensitivität)
#define CFG_FEATURE_ENABLE (1 << 0) // Benutzerzugänglich
#define CFG_DEBUG_MODE (1 << 1) // Sollte geschützt sein!
#define CFG_USER_SETTING (0x3F << 2) // Benutzerzugänglich
#define CFG_SECURITY_BYPASS (1 << 8) // Sollte geschützt sein!
// Verwundbar: Alles-oder-nichts-Sperre
bool register_locked = false;
void write_config_register(uint32_t value) {
// VERWUNDBAR: Gesamtes Register gesperrt oder entsperrt
// Keine Bit-Level-Granularität
if (!register_locked) {
*(volatile uint32_t*)CONFIG_REG_ADDR = value;
}
}
// Benutzer kann sicherheitskritische Bits setzen!
void user_configure(uint32_t user_settings) {
// Benutzer liefert vollen 32-Bit-Wert
// Nichts verhindert das Setzen von CFG_SECURITY_BYPASS oder CFG_DEBUG_MODE
write_config_register(user_settings);
}
Sichere Lösung
// Sicher: Bit-Level-Zugriffskontroll-Granularität
module secure_register_access (
input wire clk,
input wire reset_n,
input wire [31:0] write_data,
input wire write_enable,
input wire [3:0] register_select,
input wire privileged_access,
output reg [31:0] read_data
);
// Steuerregister mit Bit-Level-Schutz:
// [0] - Feature aktivieren (benutzerzugänglich)
// [1] - Debug-Modus (nur privilegiert)
// [7:2] - Konfiguration (benutzerzugänglich)
// [8] - Sicherheitsumgehung (nur privilegiert)
// [15:9] - Weitere Konfiguration (benutzerzugänglich)
// [31:16] - Reserviert (als Null lesen)
reg [31:0] control_register;
// Bitmasken für Zugriffskontrolle
localparam USER_WRITABLE_MASK = 32'h0000FEFD; // Bits die Benutzer schreiben kann
localparam PRIV_WRITABLE_MASK = 32'h0000FFFF; // Bits die Privilegierte schreiben können
localparam PROTECTED_BITS = 32'h00000102; // Debug-Modus + Sicherheitsumgehung
always @(posedge clk or negedge reset_n) begin
if (!reset_n) begin
control_register <= 32'h0;
end
else if (write_enable && register_select == 4'b0001) begin
if (privileged_access) begin
// Privilegiert: kann alle implementierten Bits schreiben
control_register <= (control_register & ~PRIV_WRITABLE_MASK) |
(write_data & PRIV_WRITABLE_MASK);
end else begin
// Benutzer: kann nur nicht-geschützte Bits schreiben
control_register <= (control_register & ~USER_WRITABLE_MASK) |
(write_data & USER_WRITABLE_MASK);
// Geschützte Bits [1] und [8] werden NICHT modifiziert
end
end
end
// Lesen gibt tatsächlichen Wert zurück (oder könnte geschützte Bits für Benutzer maskieren)
always @(*) begin
if (privileged_access) begin
read_data = control_register;
end else begin
// Optional geschützte Bits vor unprivilegierten Lesezugriffen verbergen
read_data = control_register & USER_WRITABLE_MASK;
end
end
endmodule
// Sicher: Separate Register für verschiedene Schutzstufen
module secure_separated_registers (
input wire clk,
input wire reset_n,
input wire [31:0] write_data,
input wire write_enable,
input wire [3:0] register_select,
input wire privileged_access,
output reg [31:0] read_data
);
// Register nach Sensitivität trennen
reg [31:0] user_config_register; // Adresse 0x00 - benutzerbeschreibbar
reg [31:0] security_config_register; // Adresse 0x04 - nur privilegiert
reg [31:0] debug_config_register; // Adresse 0x08 - privilegiert + Debug-Auth
always @(posedge clk or negedge reset_n) begin
if (!reset_n) begin
user_config_register <= 32'h0;
security_config_register <= 32'h0;
debug_config_register <= 32'h0;
end
else if (write_enable) begin
case (register_select)
4'b0000: begin
// Benutzerkonfiguration - immer beschreibbar
user_config_register <= write_data;
end
4'b0001: begin
// Sicherheitskonfiguration - nur privilegiert
if (privileged_access) begin
security_config_register <= write_data;
end
// Unprivilegierte Schreibvorgänge stillschweigend ignorieren
end
4'b0010: begin
// Debug-Konfiguration - erfordert erhöhte Privilegien
if (privileged_access && debug_authenticated) begin
debug_config_register <= write_data;
end
end
endcase
end
end
endmodule
// Sicher: Firmware mit Bit-Level-Zugriffskontrolle
#define CONFIG_REG_ADDR 0x40001000
// Benutzerzugängliche Bits
#define CFG_FEATURE_ENABLE (1 << 0)
#define CFG_USER_SETTING (0x3F << 2)
#define CFG_USER_DATA (0x7FFFFF << 9)
// Geschützte Bits (nur privilegierter Zugriff)
#define CFG_DEBUG_MODE (1 << 1)
#define CFG_SECURITY_BYPASS (1 << 8)
// Zugriffsmasken
#define USER_WRITABLE_MASK (CFG_FEATURE_ENABLE | CFG_USER_SETTING | CFG_USER_DATA)
#define PROTECTED_MASK (CFG_DEBUG_MODE | CFG_SECURITY_BYPASS)
void write_config_register_user(uint32_t value) {
// Aktuellen Wert lesen
uint32_t current = *(volatile uint32_t*)CONFIG_REG_ADDR;
// Geschützte Bits beibehalten, nur benutzerbeschreibbare Bits aktualisieren
uint32_t new_value = (current & ~USER_WRITABLE_MASK) |
(value & USER_WRITABLE_MASK);
*(volatile uint32_t*)CONFIG_REG_ADDR = new_value;
}
void write_config_register_privileged(uint32_t value, bool is_privileged) {
if (!is_privileged) {
// Unprivilegiert: Benutzerpfad verwenden
write_config_register_user(value);
return;
}
// Privilegiert: kann alle Bits schreiben
*(volatile uint32_t*)CONFIG_REG_ADDR = value;
}
// Sichere Benutzerkonfigurationsfunktion
void user_configure(uint32_t user_settings) {
// Maskiert automatisch geschützte Bits aus
write_config_register_user(user_settings);
// Selbst wenn Benutzer versucht SECURITY_BYPASS zu setzen, funktioniert es nicht
// Das Bit wird vor dem Schreiben ausmaskiert
}
// Validierungsfunktion
bool validate_access_control_granularity(void) {
uint32_t original = *(volatile uint32_t*)CONFIG_REG_ADDR;
// Versuchen geschützte Bits über Benutzerschnittstelle zu setzen
write_config_register_user(0xFFFFFFFF);
uint32_t after_user_write = *(volatile uint32_t*)CONFIG_REG_ADDR;
// Verifizieren dass geschützte Bits unverändert sind
if ((after_user_write & PROTECTED_MASK) != (original & PROTECTED_MASK)) {
log_error("Zugriffskontroll-Granularitätsfehler!");
return false;
}
// Original wiederherstellen
*(volatile uint32_t*)CONFIG_REG_ADDR = original;
return true;
}
Ausgenutzt in der Praxis
Cloud-Berechtigungsfehlkonfigurationen (verschiedene)
Zahlreiche Cloud-Datenlecks resultierten aus übermäßig freizügigen IAM-Richtlinien, bei denen Dienstkonten volle Admin-Berechtigungen erhielten, anstatt nur die minimalen erforderlichen Berechtigungen.
Tools zum Testen und Ausnutzen
-
Prowler — AWS-Sicherheits-Best-Practices-Assessment.
-
ScoutSuite — Multi-Cloud-Sicherheits-Auditing.
CVE-Beispiele
- CVE-2020-8555 — Kubernetes-Berechtigung erlaubte umfassenden Netzwerkzugriff statt granularer Kontrolle.
Referenzen
-
MITRE Corporation. "CWE-1220: Insufficient Granularity of Access Control." https://cwe.mitre.org/data/definitions/1220.html
-
NIST SP 800-53. "Access Control Policies."
-
OWASP. "Principle of Least Privilege."