Nur Filterung von Sonderzeichen relativ zu einer Markierung
Beschreibung
Nur Filterung von Sonderzeichen relativ zu einer Markierung ist eine Schwachstelle bei der Eingabevalidierung, bei der Software gefährliche Elemente nur filtert, wenn sie an bestimmten Positionen relativ zu String-Markierungen erscheinen, wie dem Anfang (^) oder Ende ($) eines Strings. Dieser Ansatz verwendet verankertes Muster-Matching, das nur an Grenzpositionen prüft, wodurch identische gefährliche Sequenzen durchgelassen werden, wenn sie anderswo in der Eingabe erscheinen. Der Filter nimmt an, dass Angreifer bösartigen Inhalt an vorhersehbaren Stellen platzieren werden, was leicht zu umgehen ist.
Risiko
Angreifer können markierungsrelative Filterung trivial umgehen, indem sie gefährliche Sequenzen weg von der geprüften Markierung positionieren. Wenn ein Filter "../" nur am String-Anfang entfernt, passieren Eingaben wie "x/../../../etc/passwd" oder "foo/../../../etc/passwd" völlig unverändert. Dies ist besonders gefährlich bei der Pfadbehandlung, wo jede Traversal-Sequenz, unabhängig von der Position, den Verzeichnisbaum navigieren kann. Die Schwachstelle ist häufig, wenn Entwickler Regex-Anker (^, $) verwenden, ohne zu realisieren, dass sie das Matching auf bestimmte Positionen beschränken. Selbst eine einzelne ungefilterte Instanz einer gefährlichen Sequenz kann die beabsichtigte Sicherheitskontrolle vollständig kompromittieren.
Lösung
Entfernen Sie Positionsanker aus sicherheitskritischem Muster-Matching, es sei denn, der gesamte String muss einem bestimmten Format entsprechen. Verwenden Sie globale, unverankterte Muster, die gefährliche Sequenzen überall in der Eingabe finden. Für Pfadvalidierung lösen Sie Eingaben zu kanonischen Pfaden auf und überprüfen Sie, ob sie innerhalb erlaubter Verzeichnisse verbleiben. Implementieren Sie iterative Filterung, die fortgesetzt wird, bis keine gefährlichen Muster mehr gefunden werden. Bevorzugen Sie Allowlist-Validierung, die nur bekannt sichere Zeichen akzeptiert. Wenn Anker für Formatvalidierung benötigt werden, kombinieren Sie sie mit umfassender Inhaltsvalidierung, die die gesamte Eingabe untersucht.
Häufige Auswirkungen
| Auswirkung | Details |
|---|---|
| Integrität | Bereich: Integrität Unerwarteter Zustand - Gefährliche Elemente, die weg von Markierungen positioniert sind, passieren Filter unverändert. |
| Vertraulichkeit | Bereich: Vertraulichkeit Anwendungsdaten lesen - Ungefilterte Path-Traversal-Sequenzen ermöglichen Zugriff auf sensible Dateien. |
| Integrität | Bereich: Integrität Unautorisierten Code ausführen - Injection-Sequenzen vermeiden Filterung, indem sie nach geprüften Markierungen erscheinen. |
Beispielcode
Verwundbarer Code
# Verwundbar: ^ Anker matched nur am String-Anfang
my $Username = GetUntrustedInput();
# Verwundbar: Entfernt nur "../" ganz am Anfang
$Username =~ s/^\.\.\///;
my $filename = "/home/user/" . $Username;
ReadAndSendFile($filename);
# Angriff: "../../../etc/passwd" -> entfernt erstes, lässt "../../etc/passwd"
# Angriff: "x/../../../etc/passwd" -> "../" nicht am Anfang, unverändert
# Angriff: "subdir/../../../etc/passwd" -> Präfix ermöglicht Bypass
# Verwundbar: Prüft nur ob String mit gefährlichem Muster beginnt
def vulnerable_filter(path):
# Verwundbar: Entfernt nur führende Traversal
if path.startswith('../'):
path = path[3:]
return path
# Angriff: "foo/../../../etc/passwd" - beginnt nicht mit "../"
# Angriff: "./../../etc/passwd" - beginnt mit "./" nicht "../"
Lösungscode
# Behoben: Anker entfernen, globales Matching mit Schleife verwenden
my $Username = GetUntrustedInput();
# Behoben: Kein ^-Anker - matched überall
# Schleife behandelt verschachtelte Muster
my $prev;
do {
$prev = $Username;
$Username =~ s/\.\.[\\/]//g; # Beide Trennzeichen matchen
} while ($Username ne $prev);
# Besser: Allowlist-Validierung
unless ($Username =~ /^[a-zA-Z0-9_.-]+$/) {
die "Ungültiger Benutzername";
}
my $filename = "/home/user/" . $Username;
# Behoben: Gesamten String prüfen, kanonischen Pfad verwenden
import os.path
def fixed_filter(path):
# Behoben: Von überall entfernen, Schleife bis stabil
prev = None
while path != prev:
prev = path
path = path.replace('../', '').replace('..\\', '')
return path
# Besser: Kanonische Pfadvalidierung
def fixed_validate_path(base_dir, user_path):
# Zu kanonischer Form auflösen
full_path = os.path.realpath(os.path.join(base_dir, user_path))
base_path = os.path.realpath(base_dir)
# Verifizieren, dass Ergebnis unter Basisverzeichnis ist
if not full_path.startswith(base_path + os.sep):
raise ValueError("Path-Traversal erkannt")
return full_path
Verwandte CWEs
- CWE-795: Nur Filterung von Sonderzeichen an einer bestimmten Position (Eltern)
- CWE-797: Nur Filterung von Sonderzeichen an einer absoluten Position (Geschwister)
- CWE-791: Unvollständige Filterung von Sonderzeichen (Großeltern)
- CWE-22: Unsachgemäße Einschränkung eines Pfadnamens auf ein beschränktes Verzeichnis (verwandte Ausnutzung)
Referenzen
- MITRE Corporation. "CWE-796: Only Filtering Special Elements Relative to a Marker." https://cwe.mitre.org/data/definitions/796.html
- OWASP. "Path Traversal." https://owasp.org/www-community/attacks/Path_Traversal
- Regular-Expressions.info. "Anchors." https://www.regular-expressions.info/anchors.html