Checkliste zur Implementierung der Dateivalidierung in Webformularen
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.
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älle | Erwartetes Ergebnis | zu verwendende Datei |
|---|---|---|
| Datei mit genauem Limit | Erfolg | <a href="/ja/files/threshold/">Schwellenwertdateien</a> |
| Datei, die das Limit um 1 Byte überschreitet | Fehler 413 | <a href="/ja/files/threshold/">Schwellenwertdateien</a> |
| Leere Datei mit 0 Bytes | Validierungsfehler | Manuelle Erstellung |
| Datei mit gefälschtem Dateityp (PHP → .jpg) | MIME-Fehler | <a href="/ja/files/broken/">Beschädigte Datei</a> |
| Datei mit beschädigtem Header | Validierungsfehler | <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.
- <strong>MIME-Typ-Validierung auf der Serverseite</strong>(mit <code>finfo</code>)— vertrauen Sie nicht der Clientangabe
- <strong>Mit zufälligem Dateinamen speichern</strong> — verwenden Sie nicht den ursprünglichen Dateinamen
- <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>