Skip to content

Checkliste zur Implementierung der Dateivalidierung in Webformularen

Kategorie:Sicherheit · Implementierung
Dieser Artikel ist derzeit nur auf Japanisch verfügbar. Übersetzte Versionen werden schrittweise veröffentlicht.

Die Implementierung der Datei-Upload-Funktion ist mit vielen Sicherheitsbedenken verbunden und birgt viele leicht zu übersehende Fallstricke. Dieser Artikel erklärt eine Checkliste zur Implementierung von Datei-Uploads, die sicher in einer Produktionsumgebung funktionieren.

Empfohlene Reihenfolge der Dateivalidierung Sichere Reihenfolge: von leichter zu schwerer Validierung 1. File size bytes <= max NG → sofort ablehnen 2. Extension .jpg / .png ... NG → sofort ablehnen 3. MIME type finfo / mime_content_type NG → sofort ablehnen 4. Magic bytes FF D8 FF (JPEG) ... NG → sofort ablehnen 5. Content scan ClamAV / VirusTotal NG → sofort ablehnen
Abbildung 1: Validierung durch leichte Überprüfungen zuerst ausgeführt und frühzeitige Ablehnung

Checklisten-Übersicht

Diese Checkliste konzentriert sich auf die <strong>Backend-Validierung (serverseitig)</strong>. Die Frontend-Validierung wird als zusätzliche UX-Verbesserung implementiert, bietet aber keine Sicherheitsgarantien.

1. Validierung der Dateigröße

  • <input type="checkbox" disabled> Das Upload-Limit ist in Bytes definiert (ohne Verwechslung von MB und MiB)
  • <input type="checkbox" disabled> Im Fall von PHP werden sowohl <code>upload_max_filesize</code> als auch <code>post_max_size</code> konfiguriert
  • <input type="checkbox" disabled> Im Fall von Nginx wird der Multipart-Overhead zu <code>client_max_body_size</code> addiert
  • <input type="checkbox" disabled> Es gibt Fehlerbehandlung, wenn <code>$_FILES['file']['error']</code> UPLOAD_ERR_INI_SIZE / UPLOAD_ERR_FORM_SIZE ist
  • <input type="checkbox" disabled> Prüft minimale Dateigröße(schließt 0-Byte-Dateien aus)
 $maxBytes) {
        throw new \RuntimeException(sprintf(
            'ファイルサイズ(%s)が上限(%s)を超えています',
            number_format($file['size']),
            number_format($maxBytes)
        ));
    }
}

2. Validierung des Dateiformats (MIME-Typ)

  • <input type="checkbox" disabled> Der vom Client gesendete <code>Content-Type</code> (<code>$_FILES['file']['type']</code>) wird nicht vertraut
  • <input type="checkbox" disabled> Es wird serverseitige MIME-Typ-Validierung mit <code>finfo</code> / <code>mime_content_type()</code> durchgeführt
  • <input type="checkbox" disabled> Definiert Whitelist zulässiger MIME-Typen
file($file['tmp_name']);

if (!in_array($mimeType, $allowed, true)) {
    throw new \RuntimeException('許可されていないファイル形式です: ' . $mimeType);
}

3. Validierung der Dateierweiterung

  • <input type="checkbox" disabled> Definiert Whitelist von Dateierweiterungen(nicht Blacklist)
  • <input type="checkbox" disabled> Erkennt und lehnt doppelte Dateierweiterungen ab(<code>shell.php.jpg</code>)
  • <input type="checkbox" disabled> Normalisiert und validiert Groß-/Kleinschreibung(<code>.JPG</code> und <code>.jpg</code> werden gleich behandelt)
 2) {
    throw new \RuntimeException('不正なファイル名です');
}

$ext = strtolower(pathinfo($originalName, PATHINFO_EXTENSION));
if (!in_array($ext, $allowed, true)) {
    throw new \RuntimeException('許可されていない拡張子です: ' . $ext);
}

4. Validierung von Magic Byte (Dateisignatur)

  • <input type="checkbox" disabled> Magic Bytes bei wichtigen Dateien validieren (ausgenommen ausführbare Dateien usw.)

5. Sichere Handhabung von Ziel und Dateiname

  • <input type="checkbox" disabled> Zielverzeichnis liegt außerhalb des Web-Root(oder wird über XSendFile/X-Accel-Redirect kontrolliert)
  • <input type="checkbox" disabled> Gespeicherter Dateiname wird zufällig generiert(z.B. UUID), nicht der Originalname
  • <input type="checkbox" disabled> Entfernt Path Traversal(<code>../../../etc/passwd</code>)durch Validierung
  • <input type="checkbox" disabled> Zielverzeichnis hat keine PHP-Ausführungsberechtigung(PHP deaktivieren via <code>.htaccess</code> oder Nginx-Konfiguration)

6. Fehlerbehandlung und Antwort

  • <input type="checkbox" disabled> Ein angemessener HTTP-Status (200/201) wird bei erfolgreichem Upload zurückgegeben
  • <input type="checkbox" disabled> <strong>413 Payload Too Large</strong> wird zurückgegeben, wenn die Größe überschritten wird
  • <input type="checkbox" disabled> Gibt <strong>422 Unprocessable Entity</strong> bei ungültigem Dateiformat zurück
  • <input type="checkbox" disabled> Fehlermeldungen enthalten keine internen Serverinformationen (Pfad, Version usw.)

7. Testfälle

Führen Sie nach der Implementierung die folgenden Testfälle aus, um die Funktionalität zu bestätigen. Sie können Testdateien von DevLab verwenden.

TestfälleErwartetes Ergebniszu verwendende Datei
Datei mit genauem LimitErfolg<a href="/ja/files/threshold/">Schwellenwertdateien</a>
Datei, die das Limit um 1 Byte überschreitetFehler 413<a href="/ja/files/threshold/">Schwellenwertdateien</a>
Leere Datei mit 0 BytesValidierungsfehlerManuelle Erstellung
Datei mit gefälschtem Dateityp (PHP → .jpg)MIME-Fehler<a href="/ja/files/broken/">Beschädigte Datei</a>
Datei mit beschädigtem HeaderValidierungsfehler<a href="/ja/files/broken/">Beschädigte Datei</a>

Zusammenfassung

Die Implementierung eines sicheren Datei-Uploads erfordert Validierung auf mehreren Ebenen. Sie müssen die folgenden 3 Punkte unbedingt implementieren.

  1. <strong>MIME-Typ-Validierung auf der Serverseite</strong>(mit <code>finfo</code>)— vertrauen Sie nicht der Clientangabe
  2. <strong>Mit zufälligem Dateinamen speichern</strong> — verwenden Sie nicht den ursprünglichen Dateinamen
  3. <strong>PHP-Ausführung im Zielverzeichnis deaktivieren</strong> — Verhindern, dass Skripte im Upload-Verzeichnis ausgeführt werden

Testdatei zur Verwendung in diesem Artikel

  • → <a href="/ja/files/broken/" class="text-primary-600 dark:text-primary-400 hover:underline">Liste beschädigter Dateien (zum Testen von Validierungsfehlern)</a>
  • → <a href="/ja/files/threshold/" class="text-primary-600 dark:text-primary-400 hover:underline">Liste von Schwellwert-Testdateien (9.9MB / 10MB / 10.1MB)</a>
  • → <a href="/ja/files/images/" class="text-primary-600 dark:text-primary-400 hover:underline">Liste der Bild-Testdateien (PNG / JPG / WebP / GIF)</a>

Verwandte Artikel

  • → <a href="/ja/blog/how-to-test-upload-limit/" class="text-primary-600 dark:text-primary-400 hover:underline">So testen Sie das Datei-Upload-Limit korrekt</a>
  • → <a href="/ja/reference/magic-bytes/" class="text-primary-600 dark:text-primary-400 hover:underline">Magic Bytes (Datei-Signatur) Referenz</a>