Verwendung von Pfadmanipulationsfunktion ohne Puffer maximaler Größe
Beschreibung
Verwendung von Pfadmanipulationsfunktion ohne Puffer maximaler Größe ist eine Buffer-Overflow-Schwachstelle, bei der Software Funktionen verwendet, die Dateipfade oder Verzeichnisnamen manipulieren, aber einen Ausgabepuffer bereitstellt, der kleiner als die maximal mögliche Pfadlange ist. Funktionen wie realpath(), readlink(), PathAppend(), GetFullPathName() und ähnliche Utilities können Pfade bis zur maximalen Pfadlange des Systems erzeugen (z.B. PATH_MAX, MAX_PATH). Wenn der Ausgabepuffer kleiner als dieses Maximum ist, kann die Funktion über die Puffergrenzen hinaus schreiben und einen Buffer Overflow verursachen.
Risiko
Pfadmanipulations-Buffer-Overflows können schwerwiegende Sicherheitskonsequenzen haben. Da Pfadlangen von Benutzereingaben und Dateisystemstruktur abhängen, können Angreifer möglicherweise Eingaben erstellen, die Pfade erzeugen, die den unterdimensionierten Puffer überschreiten. Dies kann angrenzenden Speicher korrumpieren, die Anwendung zum Absturz bringen oder potenziell beliebige Code-Ausführung ermöglichen. Die Schwachstelle ist besonders gefährlich, weil Entwickler oft mögliche Pfadlangen unterschätzen - Pfade können tiefe Verzeichnisverschachtelung, lange Dateinamen oder symbolische Link-Ketten enthalten, die sich während der Auflösung erweitern.
Lösung
Allozieren Sie immer Ausgabepuffer mit einer Größe gleich oder größer als die maximale Pfadlange für die Zielplattform. Auf POSIX-Systemen verwenden Sie PATH_MAX (typischerweise 4096 Bytes). Unter Windows verwenden Sie MAX_PATH (260 Zeichen) oder erweiterte Pfadbehandlung (32.767 Zeichen mit \?\-Präfix). Berücksichtigen Sie, dass PATH_MAX möglicherweise nicht auf allen Systemen definiert ist - verwenden Sie pathconf(), um Limits dynamisch zu bestimmen. Bevorzugen Sie sicherere Varianten von Funktionen wenn verfügbar (z.B. realpath() mit NULL-Argument auf Systemen, die den Puffer allozieren).
Häufige Auswirkungen
| Auswirkung | Details |
|---|---|
| Integrität | Bereich: Integrität Speicher ändern - Buffer Overflow überschreibt angrenzenden Speicher mit Pfaddaten. |
| Verfügbarkeit | Bereich: Verfügbarkeit DoS: Absturz - Speicherkorruption verursacht typischerweise Abstürze. |
| Vertraulichkeit | Bereich: Vertraulichkeit, Integrität, Verfügbarkeit Unbefugten Code ausführen - Ausnutzbare Buffer Overflows können beliebige Code-Ausführung ermöglichen. |
Beispielcode
Verwundbarer Code
// Verwundbar: Puffer kleiner als PATH_MAX
#include <stdlib.h>
#include <string.h>
#include <limits.h>
char* vulnerable_realpath(const char* path) {
// Verwundbar: Puffer ist nur 128 Bytes, PATH_MAX ist typischerweise 4096
char resolvedPath[128];
if (realpath(path, resolvedPath) == NULL) {
return NULL;
}
// Wenn tatsächlicher Pfad > 128 Bytes, ist Buffer Overflow aufgetreten!
return strdup(resolvedPath);
}
char* createOutputDirectory(const char* name) {
// Verwundbar: 128-Byte-Puffer für Pfadoperationen
char outputDirectoryName[128];
if (getCurrentDirectory(128, outputDirectoryName) == 0) {
return NULL;
}
// Verwundbar: PathAppend kann Puffer überschreiten
if (!PathAppend(outputDirectoryName, "output")) {
return NULL;
}
// Verwundbar: Hinzufügen von 'name' könnte 128-Byte-Puffer überlaufen
if (!PathAppend(outputDirectoryName, name)) {
return NULL; // Möglicherweise bereits übergelaufen
}
return strdup(outputDirectoryName);
}
Gefixter Code
// Gefixt: PATH_MAX für Puffergröße verwenden
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <errno.h>
#ifndef PATH_MAX
#include <unistd.h>
#define PATH_MAX pathconf("/", _PC_PATH_MAX)
#endif
char* fixed_realpath(const char* path) {
// Gefixt: Puffer mit PATH_MAX-Größe allozieren
char* resolvedPath = malloc(PATH_MAX);
if (resolvedPath == NULL) {
return NULL;
}
if (realpath(path, resolvedPath) == NULL) {
free(resolvedPath);
return NULL;
}
return resolvedPath;
}
// Noch besser: realpath den Puffer allozieren lassen (POSIX.1-2008)
char* fixed_realpath_v2(const char* path) {
// Gefixt: NULL-Puffer veranlasst realpath zu allozieren
// Aufrufer muss zurückgegebenen Pointer freigeben
char* resolvedPath = realpath(path, NULL);
return resolvedPath; // Kann bei Fehler NULL sein
}
// Gefixt: readlink mit ordnungsgemäßem Puffer
#include <unistd.h>
#include <stdlib.h>
#include <limits.h>
#include <errno.h>
char* fixed_readlink(const char* path) {
// Gefixt: PATH_MAX verwenden oder dynamisch bestimmen
size_t bufsize = PATH_MAX;
char* buf = malloc(bufsize);
if (buf == NULL) {
return NULL;
}
ssize_t len = readlink(path, buf, bufsize - 1);
if (len < 0) {
free(buf);
return NULL;
}
// Prüfen ob Puffer möglicherweise zu klein war
if ((size_t)len >= bufsize - 1) {
// Link-Ziel könnte abgeschnitten sein
// Könnte mit größerem Puffer wiederholen
free(buf);
errno = ENAMETOOLONG;
return NULL;
}
buf[len] = '\0';
return buf;
}
// Gefixt: Sichere Pfadkombination
#include <stdio.h>
#include <string.h>
#include <limits.h>
#include <stdlib.h>
char* fixed_combine_paths(const char* dir, const char* file) {
size_t dir_len = strlen(dir);
size_t file_len = strlen(file);
size_t total = dir_len + 1 + file_len + 1; // dir + '/' + file + '\0'
// Gefixt: Gegen PATH_MAX prüfen
if (total > PATH_MAX) {
return NULL; // Pfad wäre zu lang
}
char* result = malloc(total);
if (result == NULL) {
return NULL;
}
// Gefixt: snprintf für Bounds-Checking verwenden
int written = snprintf(result, total, "%s/%s", dir, file);
if (written < 0 || (size_t)written >= total) {
free(result);
return NULL;
}
return result;
}
Erkennungsmethoden
- Statische Analyse: SAST-Tools können Pfadmanipulationsaufrufe mit unterdimensionierten Puffern identifizieren.
- Code-Review: Nach hartcodierten Puffergrößen kleiner als PATH_MAX/MAX_PATH suchen.
- Testing: Mit tief verschachtelten Verzeichnissen und langen Dateinamen testen.
Referenzen
- MITRE Corporation. "CWE-785: Use of Path Manipulation Function without Maximum-sized Buffer." https://cwe.mitre.org/data/definitions/785.html
- CERT C Coding Standard. "FIO02-C. Canonicalize path names originating from tainted sources."
- Linux Manual. "realpath(3) - return the canonicalized absolute pathname."