Unvollständige Filterung mehrerer Instanzen von Sonderzeichen

Beschreibung

Unvollständige Filterung mehrerer Instanzen von Sonderzeichen ist eine Schwachstelle bei der Eingabevalidierung, bei der Software nicht alle Instanzen von Sonderzeichen filtert, wenn sie mehrfach in der Eingabe erscheinen. Dies betrifft sowohl sequentielle Elemente (gefährliche Sequenzen, die nebeneinander erscheinen, wie "....//") als auch nicht-sequentielle Elemente (dieselbe gefährliche Sequenz, die an mehreren Stellen in der Eingabe erscheint). Wenn die Filterung nicht alle Instanzen behandelt, können Angreifer Eingaben konstruieren, bei denen die Entfernung einiger Instanzen zusätzliche gefährliche Sequenzen erzeugt oder offenbart.

Risiko

Diese Schwachstelle ermöglicht ausgeklügelte Bypass-Techniken. Bei sequentiellen Elementen können Angreifer Eingaben wie "....//file" erstellen, bei denen das Entfernen der mittleren ".." und "/" eine neue "../"-Sequenz hinterlässt. Bei nicht-sequentiellen Elementen könnten Eingaben wie "..%2f..%2f../file" einige Traversal-Sequenzen gefiltert haben, während kodierte oder anders formatierte überleben. Das Risiko wird verstärkt, wenn die Filterung nur einmal angewendet wird, ohne zu prüfen, ob das Ergebnis nun gefährlich ist. Diese Bypasses sind besonders effektiv gegen naive Filterimplementierungen, die annehmen, ein einzelner Durchlauf sei ausreichend.

Lösung

Implementieren Sie rekursive oder iterative Filterung, die fortgesetzt wird, bis keine gefährlichen Sequenzen mehr gefunden werden. Wenden Sie die Filterung in einer Schleife an und vergleichen Sie das Ergebnis mit der vorherigen Iteration, bis sie übereinstimmen (was anzeigt, dass keine weiteren Änderungen vorgenommen wurden). Behandeln Sie alle Variationen gefährlicher Elemente einschließlich verschiedener Kodierungen, Groß-/Kleinschreibungsvariationen und Trennzeichenstile. Erwägen Sie mehrere Filterdurchläufe für verschiedene Kategorien gefährlicher Elemente. Verwenden Sie kanonische Darstellung vor der Validierung - für Pfade, lösen Sie diese in absolute kanonische Form auf, bevor Sie sie prüfen. Bevorzugen Sie Allowlist-Validierung, die nur bekannt sichere Zeichen erlaubt. Testen Sie mit komplexen verschachtelten und kodierten Eingaben.

Häufige Auswirkungen

AuswirkungDetails
IntegritätBereich: Integrität

Unerwarteter Zustand - Ungefilterte Element-Instanzen verursachen unbeabsichtigtes Anwendungsverhalten.
VertraulichkeitBereich: Vertraulichkeit

Anwendungsdaten lesen - Sequentielle Traversal-Muster, die die Filterung überleben, ermöglichen Dateizugriff.
IntegritätBereich: Integrität

Unautorisierten Code ausführen - Mehrere Kodierungsvariationen gefährlicher Elemente könnten Injection ermöglichen.

Beispielcode

Verwundbarer Code

# Verwundbar: Einzelner Durchlauf behandelt keine sequentiellen Muster
my $Username = GetUntrustedInput();

# Verwundbar: Entfernt nur literale "../"-Sequenzen
$Username =~ s/\.\.\///g;

my $filename = "/home/user/" . $Username;
ReadAndSendFile($filename);

# Angriff: "....//....//etc/passwd"
# Nach Filter: jedes ".." gefolgt von "." gefolgt von "/" wird anders
# Ergebnis kann je nach genauem Muster immer noch Traversal ermöglichen
# Verwundbar: Behandelt keine doppelt kodierten Sequenzen
import urllib.parse

def vulnerable_filter(path):
    # Erster Durchlauf: entferne Path-Traversal
    filtered = path.replace('../', '')

    # Verwundbar: Behandelt keine kodierten Versionen
    return filtered

# Angriff: "..%2f..%2fetc%2fpasswd"
# Nach Filter: unverändert weil %2f nicht / ist
# Bei URL-Dekodierung durch Webserver: "../../../etc/passwd"

Lösungscode

# Behoben: Schleife bis keine weiteren Änderungen
my $Username = GetUntrustedInput();

# Behoben: Rekursive Filterung
my $prev;
do {
    $prev = $Username;
    # Alle Varianten entfernen
    $Username =~ s/\.\.[\/\\]//g;           # Literale Traversal
    $Username =~ s/%2e%2e[%2f%5c]//gi;      # URL-kodiert
    $Username =~ s/%252e%252e[%252f%255c]//gi;  # Doppelt kodiert
} while ($Username ne $prev);

# Besser: Gegen Allowlist validieren
unless ($Username =~ /^[a-zA-Z0-9_.-]+$/) {
    die "Ungültiger Benutzername";
}

my $filename = "/home/user/" . $Username;
# Behoben: Alle Kodierungsvarianten behandeln und Schleife
import urllib.parse
import os.path

def fixed_filter(path):
    # Mehrfach dekodieren für doppelte/dreifache Kodierung
    decoded = path
    for _ in range(3):  # Bis zu dreifache Kodierung behandeln
        prev = decoded
        decoded = urllib.parse.unquote(decoded)
        if decoded == prev:
            break

    # Schleife bis stabil
    prev = None
    while decoded != prev:
        prev = decoded
        # Alle Traversal-Varianten entfernen
        decoded = decoded.replace('../', '')
        decoded = decoded.replace('..\\', '')

    return decoded

# Besser: Kanonische Pfadvalidierung verwenden
def fixed_validate_path(base_dir, user_path):
    # Benutzereingabe dekodieren
    decoded = user_path
    for _ in range(3):
        prev = decoded
        decoded = urllib.parse.unquote(decoded)
        if decoded == prev:
            break

    # Zu kanonischem Pfad auflösen
    full_path = os.path.realpath(os.path.join(base_dir, decoded))
    base_path = os.path.realpath(base_dir)

    # Verifizieren, dass es unter Basisverzeichnis ist
    if not full_path.startswith(base_path + os.sep):
        raise ValueError("Path-Traversal erkannt")

    return full_path

Verwandte CWEs

  • CWE-792: Unvollständige Filterung einer oder mehrerer Instanzen von Sonderzeichen (Eltern)
  • CWE-793: Nur Filterung einer Instanz eines Sonderzeichens (Geschwister)
  • CWE-23: Relative Path-Traversal (verwandte Ausnutzung)

Referenzen

  1. MITRE Corporation. "CWE-794: Incomplete Filtering of Multiple Instances of Special Elements." https://cwe.mitre.org/data/definitions/794.html
  2. OWASP. "Path Traversal." https://owasp.org/www-community/attacks/Path_Traversal
  3. OWASP. "Double Encoding." https://owasp.org/www-community/Double_Encoding