Verwendung nicht initialisierter Ressourcen
Beschreibung
Verwendung nicht initialisierter Ressourcen tritt auf, wenn Software eine Ressource verwendet oder darauf zugreift, die nicht ordnungsgemäß initialisiert wurde. Wenn Ressourcen wie Variablen, Speicherpuffer, Datei-Handles oder Datenstrukturen ohne Initialisierung verwendet werden, können sie unbestimmte Werte aus vorherigen Operationen oder Müll-Daten enthalten. Dies führt zu unvorhersehbarem Programmverhalten, Abstürzen, Sicherheitslücken oder Informationsoffenlegung. Das Problem ist besonders schwerwiegend in Low-Level-Sprachen, in denen Speicher nicht automatisch initialisiert wird.
Risiko
Die Verwendung nicht initialisierter Ressourcen kann schwerwiegende Sicherheitsimplikationen haben. Nicht initialisierter Speicher kann sensible Daten aus vorherigen Operationen enthalten, was zu Informationslecks führt. Nicht initialisierte Variablen, die in Sicherheitsentscheidungen verwendet werden (wie Benutzer-IDs oder Privilegienstufen), können zu privilegierten Werten defaultieren. Programme können aufgrund ungültiger Daten in nicht initialisierten Ressourcen abstürzen. Der Kontrollfluss kann auf unerwartete Weise geändert werden, wenn Verzweigungsbedingungen von nicht initialisierten Werten abhängen. In Zugriffskontroll-Kontexten können nicht initialisierte Variablen unbeabsichtigt erhöhte Privilegien gewähren.
Lösung
Initialisieren Sie Variablen, Puffer und Datenstrukturen immer vor der Verwendung. Verwenden Sie Sprachfeatures, die Initialisierung erzwingen (Konstruktoren, Initialisierungslisten). Aktivieren Sie Compiler-Warnungen für nicht initialisierte Variablenverwendung. Verwenden Sie statische Analysetools, um potenzielle Verwendung nicht initialisierter Daten zu erkennen. In C/C++ verwenden Sie memset oder calloc, um Speicherallokationen mit Null zu initialisieren. In sicherheitskritischem Code setzen Sie alle sensiblen Variablen explizit auf sichere Standardwerte. Erwägen Sie die Verwendung von Sprachen mit obligatorischer Initialisierung oder sichereren Standardwerten. Implementieren Sie defensive Programmierung mit Assertions, um den Initialisierungszustand zu verifizieren.
Häufige Auswirkungen
| Auswirkung | Details |
|---|---|
| Vertraulichkeit | Bereich: Vertraulichkeit Anwendungsdaten lesen - Nicht initialisierte Ressource kann sensible Daten aus vorherigen Verwendungen enthalten, was zu Informationsoffenlegung führt. |
| Verfügbarkeit | Bereich: Verfügbarkeit DoS: Absturz/Beenden/Neustart - Nicht initialisierte Werte können Programmflussänderungen verursachen, die zu Abstürzen oder unerwarteten Beendigungen führen. |
| Integrität, Zugriffskontrolle | Bereich: Integrität, Zugriffskontrolle Privilegien erlangen - Nicht initialisierte Variablen in Sicherheitsentscheidungen können zu privilegierten Werten defaultieren. |
Beispielcode + Lösungscode
Verwundbarer Code
// Verwundbar: Nicht initialisierter Puffer mit strcat
#include <stdio.h>
#include <string.h>
void vulnerable_concat(char *input) {
char buffer[100]; // Nicht initialisiert!
// Verwundbar: strcat fügt an existierenden Inhalt an
// buffer enthält Müll, strcat sucht nach Null-Terminator
strcat(buffer, input); // Kann überlaufen oder Müll lesen
printf("Ergebnis: %s\n", buffer);
}
// Angriff: buffer kann langen Müll vor Null enthalten
// was strcat zum Überlauf bringt, wenn es schließlich Null findet
// Verwundbar: Nicht initialisierte Variable im bedingten Pfad
int vulnerable_process_data(int flag, int *result) {
int value; // Nicht initialisiert!
if (flag == 1) {
value = compute_value();
}
// Verwundbar: wenn flag != 1, bleibt value nicht initialisiert
*result = value; // Kann Müll-Wert verwenden
return 0;
}
// Verwundbar: Nicht initialisierte UID in Zugriffskontrolle
#include <unistd.h>
int vulnerable_check_access(char *username) {
uid_t uid; // Nicht initialisiert - kann zu 0 (root) defaultieren!
if (username != NULL && strlen(username) > 0) {
uid = lookup_user_id(username);
}
// Verwundbar: Wenn username NULL oder leer ist, ist uid nicht initialisiert
// Auf vielen Systemen kann Stack-Speicher 0 enthalten, was Root-Zugriff gewährt
if (uid == 0) {
return ADMIN_ACCESS; // Unbeabsichtigt gewährt!
}
return USER_ACCESS;
}
Sicherer Code
// Behoben: Puffer vor Verwendung initialisieren
#include <stdio.h>
#include <string.h>
void fixed_concat(char *input) {
char buffer[100];
// Behoben: Puffer als leeren String initialisieren
buffer[0] = '\0';
// Oder verwenden: memset(buffer, 0, sizeof(buffer));
// Jetzt funktioniert strcat korrekt
if (input != NULL && strlen(input) < sizeof(buffer)) {
strcat(buffer, input);
}
printf("Ergebnis: %s\n", buffer);
}
// Behoben: Variable initialisieren und sicherstellen, dass alle Pfade sie setzen
int fixed_process_data(int flag, int *result) {
int value = 0; // Behoben: Auf sicheren Standard initialisieren
if (flag == 1) {
value = compute_value();
} else {
// Behoben: Andere Fälle explizit behandeln
value = default_value();
}
*result = value;
return 0;
}
// Behoben: UID auf unprivilegierten Wert initialisieren
#include <unistd.h>
int fixed_check_access(char *username) {
// Behoben: Auf unprivilegierten Wert initialisieren
uid_t uid = (uid_t)-1; // -1 ist typischerweise "nobody" oder ungültig
if (username != NULL && strlen(username) > 0) {
uid = lookup_user_id(username);
// Verifizieren, dass Lookup erfolgreich war
if (uid == (uid_t)-1) {
return ACCESS_DENIED;
}
} else {
// Behoben: Zugriff für ungültige Eingabe explizit verweigern
return ACCESS_DENIED;
}
if (uid == 0) {
return ADMIN_ACCESS;
}
return USER_ACCESS;
}
CVE-Beispiele
- CVE-2019-9805: Speicherkorruption durch Verwendung eines nicht initialisierten Wertes beim Lesen von Daten.
- CVE-2008-0081: Codeausführung möglich durch nicht initialisierte Variablen in Parsing-Logik.
- CVE-2008-2934: Absturz durch Verwendung eines freigegebenen, nicht initialisierten Zeigers.
- CVE-2008-4197: Privilegieneskalation durch nicht initialisierten Speicherzugriff.
- CVE-2007-4682: Informationsoffenlegung durch nicht initialisierten Speicherlesevorgang.
Verwandte CWEs
- CWE-665: Unsachgemäße Initialisierung (Eltern)
- CWE-457: Verwendung nicht initialisierter Variablen (Kind)
- CWE-909: Fehlende Initialisierung von Ressourcen (verwandt)
- CWE-824: Zugriff auf nicht initialisierten Pointer (verwandt)
Referenzen
- MITRE Corporation. "CWE-908: Use of Uninitialized Resource." https://cwe.mitre.org/data/definitions/908.html
- CERT C Secure Coding Standard. "EXP33-C. Do not read uninitialized memory."
- CERT C Secure Coding Standard. "DCL30-C. Declare objects with appropriate storage durations."