Unsachgemäße Ressourcensperrung
Beschreibung
Unsachgemäße Ressourcensperrung ist eine Schwachstelle, bei der ein Produkt eine Ressource nicht sperrt oder nicht korrekt sperrt, wenn das Produkt exklusiven Zugriff auf diese Ressource haben muss. Unzureichende Ressourcensperrung ermöglicht es Angreifern oder nebenläufigen Prozessen, Ressourcen während aktiver Operationen zu modifizieren. Diese Verletzung der Produktannahmen bezüglich Ressourcenstabilität kann unerwartete Verhaltensweisen, Datenkorruption und Systemausfälle verursachen. Die Schwachstelle manifestiert sich, wenn Mutex-Sperren nicht erworben werden, Sperrakquisitionsfehler nicht geprüft werden oder Synchronisationsmechanismen unsachgemäß implementiert sind.
Risiko
Unsachgemäße Ressourcensperrung erzeugt Race Conditions, die Datenkorruption und Sicherheitsumgehungen ermöglichen. In Finanzanwendungen können unsynchronisierte Kontooperationen durch Race Conditions zu Geldverlust oder -gewinn führen. In Multithread-Anwendungen können ungeschützte gemeinsam genutzte Ressourcen zu Use-After-Free-Schwachstellen führen, wenn ein Thread Speicher freigibt, während ein anderer ihn verwendet. Datenbankoperationen ohne ordnungsgemäße Sperrung können Dateninkonsistenzen verursachen. Die unvorhersehbare Natur von Race Conditions macht diese Fehler während des Testens schwer zu erkennen, aber leicht in der Produktion ausnutzbar.
Lösung
Implementieren Sie Synchronisationsmechanismen konsistent bei jedem Zugriff auf gemeinsam genutzte Ressourcen. Verwenden Sie sprachbereitgestellte Synchronisationsprimitive (synchronized-Schlüsselwort in Java, Mutexe in C/C++, Locks in Python). Prüfen Sie immer Rückgabewerte von Sperrakquisitionsfunktionen, um Fehler angemessen zu behandeln. Verwenden Sie RAII-Muster oder try-finally-Blöcke, um sicherzustellen, dass Sperren auch bei Ausnahmen freigegeben werden. Erwägen Sie die Verwendung von lock-freien Datenstrukturen wo angemessen. Wenden Sie das Prinzip des minimalen Sperrbereichs an—halten Sie Sperren so kurz wie nötig. Verwenden Sie statische Analysetools zur Erkennung fehlender Synchronisation.
Häufige Auswirkungen
| Auswirkung | Details |
|---|---|
| Integrität | Umfang: Integrität, Verfügbarkeit Anwendungsdaten modifizieren - Angreifer können Anwendungsdaten durch Race Conditions ändern. DoS: Instabilität - System kann durch gleichzeitige Modifikationen instabil werden. DoS: Absturz, Beendigung oder Neustart - Prozessbeendigung oder Neustart-Szenarien können auftreten. |
Beispielcode
Anfälliger Code
// Anfällig: Keine Fehlerprüfung bei Mutex-Sperre
#include <pthread.h>
void vulnerable_function(pthread_mutex_t *mutex) {
// Anfällig: Ignoriert Rückgabewert
// Sperre kann fehlschlagen, Ressource bleibt ungeschützt
pthread_mutex_lock(mutex);
/* auf gemeinsame Ressource zugreifen */
modify_shared_data();
pthread_mutex_unlock(mutex);
}
// Anfällig: Überhaupt keine Sperrung
int shared_counter = 0;
void vulnerable_increment() {
// Anfällig: Race Condition - nicht atomar
shared_counter++; // Lesen-Modifizieren-Schreiben ohne Sperre
}
// Anfällig: Unsynchronisierte Bankkontooperationen
public class VulnerableBankAccount {
private double accountBalance;
// Anfällig: Keine Synchronisation
public void deposit(double depositAmount) {
// Race Condition: anderer Thread kann zwischen diesen Operationen lesen/schreiben
double newBalance = accountBalance + depositAmount;
accountBalance = newBalance;
}
// Anfällig: Keine Synchronisation
public void withdraw(double withdrawAmount) {
double newBalance = accountBalance - withdrawAmount;
accountBalance = newBalance;
}
// Anfällig: Check-then-act Race Condition
public void transferTo(VulnerableBankAccount other, double amount) {
if (accountBalance >= amount) {
// Anderer Thread kann zwischen Prüfung und Überweisung abheben
this.withdraw(amount);
other.deposit(amount);
}
}
}
# Anfällig: Unsynchronisierte gemeinsame Ressource
import threading
class VulnerableCounter:
def __init__(self):
self.count = 0
# Anfällig: Keine Sperrung
def increment(self):
# Race Condition: Lesen, Inkrementieren, Schreiben nicht atomar
current = self.count
self.count = current + 1
# Anfällig: Check-then-act
def increment_if_below(self, limit):
if self.count < limit:
# Anderer Thread kann zwischen Prüfung und Inkrement inkrementieren
self.increment()
Korrigierter Code
// Korrigiert: Ordnungsgemäße Fehlerprüfung bei Mutex-Operationen
#include <pthread.h>
#include <errno.h>
int secure_function(pthread_mutex_t *mutex) {
// Korrigiert: Rückgabewert prüfen
int result = pthread_mutex_lock(mutex);
if (result != 0) {
log_error("Mutex-Akquisition fehlgeschlagen: %d", result);
return result; // Fehler angemessen behandeln
}
/* auf gemeinsame Ressource zugreifen */
modify_shared_data();
// Korrigiert: Auch Unlock-Ergebnis prüfen
result = pthread_mutex_unlock(mutex);
if (result != 0) {
log_error("Mutex-Freigabe fehlgeschlagen: %d", result);
}
return result;
}
// Korrigiert: Atomare Operationen oder ordnungsgemäße Sperrung
#include <stdatomic.h>
atomic_int shared_counter = 0;
void secure_increment() {
// Korrigiert: Atomare Operation
atomic_fetch_add(&shared_counter, 1);
}
// Alternative: Mutex verwenden
pthread_mutex_t counter_mutex = PTHREAD_MUTEX_INITIALIZER;
int protected_counter = 0;
void secure_increment_with_mutex() {
pthread_mutex_lock(&counter_mutex);
protected_counter++;
pthread_mutex_unlock(&counter_mutex);
}
// Korrigiert: Synchronisierte Bankkontooperationen
public class SecureBankAccount {
private double accountBalance;
private final Object balanceLock = new Object();
// Korrigiert: Synchronisierte Methode
public synchronized void deposit(double depositAmount) {
double newBalance = accountBalance + depositAmount;
accountBalance = newBalance;
}
// Korrigiert: Synchronisierte Methode
public synchronized void withdraw(double withdrawAmount) {
double newBalance = accountBalance - withdrawAmount;
accountBalance = newBalance;
}
// Korrigiert: Atomare Prüfung und Überweisung
public synchronized void transferTo(SecureBankAccount other, double amount) {
if (accountBalance >= amount) {
this.withdraw(amount);
other.deposit(amount);
}
}
}
// Alternative: ReentrantLock für mehr Kontrolle verwenden
import java.util.concurrent.locks.ReentrantLock;
public class SecureBankAccountWithLock {
private double balance;
private final ReentrantLock balanceChangeLock = new ReentrantLock();
public void deposit(double amount) {
balanceChangeLock.lock();
try {
balance = balance + amount;
} finally {
// Korrigiert: Immer im finally-Block freigeben
balanceChangeLock.unlock();
}
}
public void withdraw(double amount) {
balanceChangeLock.lock();
try {
balance = balance - amount;
} finally {
balanceChangeLock.unlock();
}
}
public boolean tryTransfer(SecureBankAccountWithLock other, double amount) {
// Korrigiert: Try-Lock um Deadlock zu vermeiden
if (balanceChangeLock.tryLock()) {
try {
if (balance >= amount) {
balance -= amount;
other.deposit(amount);
return true;
}
} finally {
balanceChangeLock.unlock();
}
}
return false;
}
}
# Korrigiert: Ordnungsgemäß synchronisierte gemeinsame Ressource
import threading
class SecureCounter:
def __init__(self):
self.count = 0
self.lock = threading.Lock()
# Korrigiert: Sperre vor Zugriff auf gemeinsame Daten erwerben
def increment(self):
with self.lock: # Erwirbt und gibt automatisch frei
current = self.count
self.count = current + 1
# Korrigiert: Atomare Prüfung-und-Inkrement
def increment_if_below(self, limit):
with self.lock:
if self.count < limit:
self.count += 1
return True
return False
# Korrigiert: Sicheres Lesen
def get_count(self):
with self.lock:
return self.count
# Alternative: RLock für reentrant-Sperrung verwenden
class SecureCounterReentrant:
def __init__(self):
self.count = 0
self.lock = threading.RLock() # Reentrant-Sperre
def increment(self):
with self.lock:
self.count += 1
def increment_multiple(self, times):
with self.lock:
for _ in range(times):
self.increment() # Sicher: RLock erlaubt Wiedereintritt
CVE-Beispiele
- CVE-2022-20141 — Betriebssystem-Kernel mit unzureichender Ressourcensperrung führt zu Use-After-Free-Schwachstelle.
Referenzen
- MITRE Corporation. "CWE-413: Improper Resource Locking." https://cwe.mitre.org/data/definitions/413.html
- Oracle. "Java Concurrency Tutorial - Synchronization." https://docs.oracle.com/javase/tutorial/essential/concurrency/sync.html