Buffer Underwrite ('Buffer Underflow')
Beschreibung
Buffer Underwrite (auch bekannt als Buffer Underflow) tritt auf, wenn ein Programm in Speicherstellen vor dem Anfang eines allokierten Puffers schreibt. Dies geschieht typischerweise, wenn Pointer-Arithmetik oder Array-Indizierung einen Wert produziert, der Speicher vor der Startadresse des Puffers referenziert. Häufige Ursachen sind das Dekrementieren von Pointern über Puffergrenzen hinaus, die Verwendung negativer Array-Indizes oder Integer-Underflows bei Indexberechnungen. Buffer Underwrites können Speicherstrukturen beschädigen, die sich vor dem Zielpuffer befinden, einschließlich Heap-Metadaten, anderer Variablen oder Kontrollstrukturen.
Risiko
Buffer Underwrites sind gefährlich, weil sie kritische Datenstrukturen beschädigen können, die dem Zielpuffer im Speicher vorausgehen. Bei Heap-Allokationen kann dies Heap-Metadaten vorheriger Chunks beschädigen und Exploitation durch Heap-Verwaltungsfunktionen ermöglichen. Auf dem Stack können Underwrites gespeicherte Register, Rücksprungadressen oder lokale Variablen aufrufender Funktionen beschädigen. Obwohl weniger häufig als Buffer Overflows, können Underwrites bei Ausnutzbarkeit gleichermaßen verheerend sein. Die Beschädigung vorausgehender Datenstrukturen führt oft zu Exploitation-Szenarien ähnlich wie Use-After-Free oder Arbitrary-Write-Bedingungen.
Lösung
Validieren Sie immer Array-Indizes und Pointer-Arithmetik, um sicherzustellen, dass sie innerhalb gültiger Puffergrenzen bleiben. Prüfen Sie sowohl auf Verletzungen der oberen als auch der unteren Grenze. Verwenden Sie unsigned Integer-Typen für Array-Indizes, wo negative Werte ungültig sind. Implementieren Sie sichere Pufferzugriffsfunktionen, die Grenzen in beide Richtungen verifizieren. Verwenden Sie speichersichere Sprachen oder C++-Container, die Out-of-bounds-Zugriff verhindern. Aktivieren Sie AddressSanitizer während der Entwicklung, um Underwrites zu erkennen. Führen Sie Code-Reviews durch mit Fokus auf Pointer-Arithmetik-Operationen, besonders solche mit Subtraktion oder negativen Offsets.
Häufige Auswirkungen
| Auswirkung | Details |
|---|---|
| Integrität | Bereich: Integrität Speicher vor dem Puffer wird beschädigt, potenziell einschließlich Heap-Metadaten, anderer Variablen oder Kontrollstrukturen. |
| Zugriffskontrolle | Bereich: Code-Ausführung Wenn der Angreifer den Underwrite-Offset und -Wert kontrolliert, kann beliebige Code-Ausführung durch beschädigte Funktionspointer oder Heap-Metadaten erreicht werden. |
| Verfügbarkeit | Bereich: Verfügbarkeit Beschädigte Speicherstrukturen verursachen typischerweise Abstürze bei nachfolgenden Speicheroperationen. |
Beispielcode + Lösungscode
Anfälliger Code
#include <string.h>
#include <stdlib.h>
// ANFÄLLIG: Negativer Index-Underwrite
void process_data(int *data, int index, int value) {
// Keine Prüfung auf negativen Index
data[index] = value; // Underwrite wenn index < 0
}
// ANFÄLLIG: Pointer-Arithmetik-Underflow
void copy_reversed(char *dest, char *src, size_t len) {
char *end = src + len - 1;
// Bug: Schleife geht über Pufferanfang hinaus
while (end >= src - 10) { // Off-by-many-Fehler
*dest++ = *end--; // Liest vor src-Puffer
}
}
// ANFÄLLIG: Integer-Underflow in Index-Berechnung
void write_at_offset(char *buffer, unsigned int user_offset, char value) {
// user_offset ist unsigned, aber Subtraktion kann unterlaufen
int index = user_offset - 100; // Unterläuft wenn user_offset < 100
buffer[index] = value; // Großer negativer Index
}
Korrigierter Code
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
// SICHER: Grenzenprüfung für beide Enden
bool process_data_safe(int *data, size_t data_size, int index, int value) {
// Auf negativen Index UND obere Grenze prüfen
if (index < 0 || (size_t)index >= data_size) {
return false; // Ungültigen Index ablehnen
}
data[index] = value;
return true;
}
// SICHER: Ordnungsgemäße Schleifengrenzen
void copy_reversed_safe(char *dest, size_t dest_size,
const char *src, size_t src_len) {
if (src_len == 0 || src_len > dest_size) {
return;
}
const char *end = src + src_len - 1;
// Nur iterieren, solange innerhalb des gültigen Quellbereichs
for (size_t i = 0; i < src_len; i++) {
dest[i] = *end--;
}
}
// SICHER: Offset vor Arithmetik validieren
bool write_at_offset_safe(char *buffer, size_t buffer_size,
size_t user_offset, char value) {
// Sicherstellen, dass Offset groß genug ist und Ergebnis in Puffer passt
if (user_offset < 100) {
return false; // Würde unterlaufen
}
size_t index = user_offset - 100;
if (index >= buffer_size) {
return false; // Würde überläufen
}
buffer[index] = value;
return true;
}
Ausgenutzt in der Praxis
Fortinet Buffer Underflow (Fortinet, 2025)
CVE-2025-Serie-Schwachstellen in Fortinet-Produkten enthielten Buffer-Underflow-Bedingungen, die für Code-Ausführung auf Netzwerk-Sicherheitsappliances ausgenutzt werden könnten.
Zoom Client Buffer Underflow (Zoom, 2025)
Buffer-Underflow-Schwachstellen in Zoom-Apps und -SDKs (März 2025) könnten Angreifern ermöglichen, Meeting-Teilnehmer durch manipulierte Daten zu kompromittieren.
Dell NetWorker Buffer Underflow (Dell, 2025)
Kritische Buffer-Underflow-Schwachstelle in Dell NetWorker Management Console-Drittanbieterkomponenten mit öffentlich verfügbarem Exploit.
Tools zum Testen/Ausnutzen
-
AddressSanitizer — erkennt Buffer Underwrites zur Laufzeit mit präziser Standortmeldung.
-
Valgrind — Speicherfehlerdetektor, der ungültigen Speicherzugriff vor Pufferstart identifiziert.
-
AFL++ — Fuzzer, der effektiv bei der Entdeckung von Grenzbedingungsfehlern einschließlich Underwrites ist.
CVE-Beispiele
-
CVE-2023-27997 — Fortinet FortiOS Buffer Underflow ermöglicht RCE.
-
CVE-2022-42475 — Fortinet FortiOS SSL-VPN Heap Buffer Underflow, in freier Wildbahn ausgenutzt.
-
CVE-2021-32760 — containerd Buffer-Underflow-Schwachstelle.
Referenzen
-
MITRE. "CWE-124: Buffer Underwrite ('Buffer Underflow')." https://cwe.mitre.org/data/definitions/124.html
-
CERT. "ARR30-C. Do not form or use out-of-bounds pointers or array subscripts." https://wiki.sei.cmu.edu/confluence/display/c/ARR30-C