Null-Byte-Interaktionsfehler (Poison Null Byte)

Beschreibung

Null-Byte-Interaktionsfehler tritt auf, wenn Anwendungen Benutzereingaben verarbeiten, die Null-Bytes (\x00) enthalten, die Diskrepanzen in der String-Behandlung zwischen verschiedenen Komponenten verursachen. Einige Sprachen (C, PHP) behandeln Null-Bytes als String-Terminatoren, während andere (Java, Python) sie als reguläre Zeichen einbeziehen. Diese Diskrepanz ermöglicht Angreifern, Sicherheitsfilter zu umgehen und auf unbefugte Ressourcen zuzugreifen.

Risiko

Angreifer können Dateierweiterungs-Validierung umgehen, um bösartige Dateien hochzuladen. Path-Traversal-Angriffe können Sicherheitsfilter umgehen. Zugriffskontrollmechanismen, die auf String-Matching basieren, können umgangen werden. Log-Injection und -Vergiftung wird möglich. SQL-Injection- und XSS-Filter können umgangen werden. Die Schwachstelle ist besonders gefährlich in Webanwendungen, die mit C-basierten Bibliotheken interagieren.

Lösung

Entfernen oder lehnen Sie Null-Bytes aus allen Benutzereingaben ab. Verwenden Sie Funktionen, die Null-Bytes korrekt behandeln. Validieren Sie Eingaben vor und nach der Null-Byte-Verarbeitung. Verwenden Sie sprachgerechte String-Behandlung. Implementieren Sie Defense in Depth mit mehreren Validierungsschichten. Berücksichtigen Sie den gesamten Datenfluss und alle beteiligten Komponenten.

Häufige Auswirkungen

AuswirkungDetails
ZugriffskontrolleBereich: Bypass

Sicherheitsfilter erkennen bösartigen Inhalt nicht.
IntegritätBereich: Dateisystem

Unbefugter Dateizugriff oder Uploads.
VertraulichkeitBereich: Informationsoffenlegung

Lesen von Dateien außerhalb des beabsichtigten Bereichs.

Beispielcode + Lösungscode

Verwundbarer Code

<?php
// VERWUNDBAR: Null-Byte-Injection in Dateieinbindung
function includePageVulnerable($page) {
    // Nur .php-Dateien erlauben
    if (substr($page, -4) !== '.php') {
        $page .= '.php';
    }

    // Auf Path-Traversal prüfen
    if (strpos($page, '..') !== false) {
        die('Ungültiger Pfad');
    }

    include '/var/www/pages/' . $page;
}

// Angriff: page=../../etc/passwd%00
// In älterem PHP schneidet das Null-Byte den String ab
// include('/var/www/pages/../../etc/passwd') wird ausgeführt!

// VERWUNDBAR: Datei-Upload-Erweiterungs-Prüfung
function uploadFileVulnerable($filename, $content) {
    $allowed = ['jpg', 'png', 'gif'];

    // Erweiterung holen
    $ext = pathinfo($filename, PATHINFO_EXTENSION);

    if (!in_array(strtolower($ext), $allowed)) {
        die('Ungültiger Dateityp');
    }

    // Angriff: filename=malware.php%00.jpg
    // Passiert Prüfung aber erstellt .php-Datei
    file_put_contents('/uploads/' . $filename, $content);
}

// VERWUNDBAR: Zugriffskontroll-Bypass
function checkAccessVulnerable($path) {
    $restricted = ['/admin/', '/config/', '/private/'];

    foreach ($restricted as $dir) {
        if (strpos($path, $dir) !== false) {
            return false;
        }
    }

    return true;
}

// Angriff: path=/adm%00in/secret.txt
// strpos findet '/admin/' nicht aber Dateisystem interpretiert als /admin/
?>
# VERWUNDBAR: Pfadvalidierungs-Bypass
import os

def read_file_vulnerable(user_path):
    base_dir = '/var/www/public/'

    # Einfache Path-Traversal-Prüfung
    if '..' in user_path:
        raise ValueError('Ungültiger Pfad')

    # Erlaubte Erweiterung prüfen
    if not user_path.endswith('.txt'):
        raise ValueError('Nur .txt-Dateien erlaubt')

    # Null-Byte nicht entfernt!
    full_path = base_dir + user_path

    # Wenn an C-Bibliothek oder bestimmte OS-Aufrufe übergeben:
    # user_path = "secret.php\x00.txt"
    # Passiert Python-Prüfungen aber C sieht "secret.php"

    with open(full_path, 'r') as f:
        return f.read()

# VERWUNDBAR: URL-/Befehlskonstruktion
def fetch_url_vulnerable(user_url):
    # Validierung
    if not user_url.startswith('https://allowed.com/'):
        raise ValueError('URL nicht erlaubt')

    # Null-Byte kann in nachgelagerter Verarbeitung abschneiden
    # user_url = "https://allowed.com/\x00https://evil.com/"
    import subprocess
    subprocess.run(['curl', user_url])  # Kann zu evil.com gehen
// VERWUNDBAR: Java übergibt an nativen Code
public class VulnerableFileHandler {

    // Java-Strings enthalten Null-Bytes
    public byte[] readFile(String userPath) throws IOException {
        // Validierung in Java
        if (userPath.contains("..")) {
            throw new SecurityException("Path-Traversal erkannt");
        }

        if (!userPath.endsWith(".txt")) {
            throw new SecurityException("Ungültige Erweiterung");
        }

        // Wenn Pfad an nativen (JNI) Code oder C-Bibliothek übergeben wird:
        // userPath = "secret.php\0.txt"
        // Java sieht "secret.php\0.txt" (11 Zeichen)
        // C sieht "secret.php" (10 Zeichen, stoppt bei Null)

        return Files.readAllBytes(Paths.get(userPath));
    }

    // VERWUNDBAR: Befehlsausführung
    public void runCommand(String filename) throws IOException {
        // Dateinamen validieren
        if (!filename.matches("[a-zA-Z0-9]+\\.sh")) {
            throw new SecurityException("Ungültiger Dateiname");
        }

        // Null-Byte in Mitte des Strings
        // filename = "safe\0; rm -rf /.sh"
        Runtime.getRuntime().exec("/scripts/" + filename);
    }
}

Lösungscode

<?php
// SICHER: Null-Bytes aus allen Eingaben entfernen
function sanitizeInput($input) {
    // Null-Bytes entfernen
    return str_replace("\0", '', $input);
}

// SICHER: Dateieinbindung mit Null-Byte-Schutz
function includePageSafe($page) {
    // Null-Bytes zuerst entfernen
    $page = str_replace(["\0", "\x00", "%00"], '', $page);

    // Erlaubte Seiten mit Whitelist
    $allowed = ['home', 'about', 'contact', 'products'];

    if (!in_array($page, $allowed)) {
        die('Ungültige Seite');
    }

    include '/var/www/pages/' . $page . '.php';
}

// SICHER: Datei-Upload mit umfassender Validierung
function uploadFileSafe($filename, $content) {
    // Null-Bytes entfernen
    $filename = str_replace(["\0", "\x00"], '', $filename);

    // Dateinamen-Format validieren
    if (!preg_match('/^[a-zA-Z0-9_-]+\.[a-zA-Z0-9]+$/', $filename)) {
        die('Ungültiges Dateinamens-Format');
    }

    // Erweiterung prüfen
    $allowed = ['jpg', 'png', 'gif'];
    $ext = strtolower(pathinfo($filename, PATHINFO_EXTENSION));

    if (!in_array($ext, $allowed)) {
        die('Ungültiger Dateityp');
    }

    // Verifizieren, dass Inhalt dem behaupteten Typ entspricht
    $finfo = finfo_open(FILEINFO_MIME_TYPE);
    $mime = finfo_buffer($finfo, $content);
    finfo_close($finfo);

    $allowedMimes = ['image/jpeg', 'image/png', 'image/gif'];
    if (!in_array($mime, $allowedMimes)) {
        die('Inhalt stimmt nicht mit Erweiterung überein');
    }

    // Sicheren Dateinamen generieren
    $safeFilename = bin2hex(random_bytes(16)) . '.' . $ext;

    file_put_contents('/uploads/' . $safeFilename, $content);
    return $safeFilename;
}

// SICHER: Zugriffskontrolle mit Null-Byte-Behandlung
function checkAccessSafe($path) {
    // Null-Bytes entfernen
    $path = str_replace(["\0", "\x00"], '', $path);

    // Pfad normalisieren
    $path = realpath('/var/www' . $path);

    // Muss innerhalb erlaubtem Verzeichnis sein
    if ($path === false || strpos($path, '/var/www/public/') !== 0) {
        return false;
    }

    return true;
}
?>
import os
import re

# SICHER: Null-Bytes aus Eingabe entfernen
def sanitize_input(user_input):
    if isinstance(user_input, str):
        return user_input.replace('\x00', '')
    elif isinstance(user_input, bytes):
        return user_input.replace(b'\x00', b'')
    return user_input

# SICHER: Pfadvalidierung mit Null-Byte-Schutz
def read_file_safe(user_path):
    base_dir = '/var/www/public/'

    # Null-Bytes entfernen
    user_path = sanitize_input(user_path)

    # Zeichen mit Whitelist
    if not re.match(r'^[a-zA-Z0-9_/-]+\.txt

```java
// SICHER: Null-Byte-Schutz in Java
public class SafeFileHandler {

    // Null-Bytes aus String entfernen
    private String sanitize(String input) {
        if (input == null) return null;
        return input.replace("\0", "");
    }

    public byte[] readFile(String userPath) throws IOException {
        // Null-Bytes entfernen
        userPath = sanitize(userPath);

        // Pfadformat validieren
        if (!userPath.matches("^[a-zA-Z0-9_/-]+\\.txt$")) {
            throw new SecurityException("Ungültiges Pfadformat");
        }

        // Pfad auflösen und validieren
        Path basePath = Paths.get("/var/www/public").toRealPath();
        Path fullPath = basePath.resolve(userPath).normalize();

        // Sicherstellen innerhalb Basisverzeichnis
        if (!fullPath.startsWith(basePath)) {
            throw new SecurityException("Pfad außerhalb erlaubtem Verzeichnis");
        }

        return Files.readAllBytes(fullPath);
    }

    // SICHER: Befehlsausführung mit Validierung
    public void runCommand(String filename) throws IOException {
        // Null-Bytes entfernen
        filename = sanitize(filename);

        // Strikte Whitelist-Validierung
        if (!filename.matches("^[a-z]+\\.sh$")) {
            throw new SecurityException("Ungültiger Dateiname");
        }

        // Verifizieren, dass Datei am erwarteten Ort existiert
        Path scriptPath = Paths.get("/scripts", filename).toRealPath();
        if (!scriptPath.startsWith(Paths.get("/scripts").toRealPath())) {
            throw new SecurityException("Script nicht in erlaubtem Verzeichnis");
        }

        // ProcessBuilder für Sicherheit verwenden
        ProcessBuilder pb = new ProcessBuilder(scriptPath.toString());
        pb.directory(new File("/scripts"));
        pb.start();
    }
}

Ausgenutzt in der Praxis

PHP-Dateieinbindung

Null-Byte-Angriffe wurden weitgehend gegen PHP include() und require() verwendet.

Datei-Upload-Bypass

Erweiterungsvalidierung umgangen um Web-Shells hochzuladen.

WAF-Bypass

Web Application Firewalls mit Null-Bytes umgangen.


Tools zum Testen/Ausnutzen

  • Burp Suite — Null-Bytes in Anfragen injizieren.
  • Manuelles Testen mit %00 in URLs und Parametern.
  • Fuzzing-Tools mit Null-Byte-Payloads.

CVE-Beispiele

  • CVE-2006-7243: PHP-Null-Byte in Dateioperationen.
  • Mehrere CVEs in Webanwendungen mit Null-Byte-Schwachstellen.

Referenzen

  1. MITRE. "CWE-626: Null Byte Interaction Error (Poison Null Byte)." https://cwe.mitre.org/data/definitions/626.html
  2. OWASP. "Embedding Null Code."