Sichere Datei-Uploads: Quarantäne, Scan und Veröffentlichungspipeline
Für Nutzer sieht ein Datei-Upload einfach aus: Datei auswählen, Fortschrittsbalken beobachten und den Inhalt sehen. Für ein System ist er eine der komplexesten Eingaben von außen. Dateiname, Endung, MIME-Typ und selbst die vom Browser gemeldete Größe sind nicht vertrauenswürdig. Die Datei kann schädlichen Inhalt, eine unerwartete Größe oder ein falsches Format, sensible Daten oder ein aufwendig zu verarbeitendes Dokument enthalten.
Das zentrale Prinzip lautet: Dass eine Datei den Speicher erreicht, macht sie nicht automatisch sicher oder veröffentlichbar für den Rest der Anwendung. Annahme, Prüfung und Veröffentlichung müssen getrennte Zustände sein. Das verkleinert die Angriffsfläche und erklärt Nutzern korrekt, warum eine Datei noch nicht sichtbar ist.
Upload als Zustandsfluss modellieren
Explizite Dateizustände verbessern Sicherheit und Nutzererfahrung zugleich. Ein einfaches Modell lautet:
selected → uploading → received → scanning → approved → published
└→ rejected
└→ failed
received bedeutet, dass die Datei Object Storage erreicht hat; approved bedeutet, dass sie Sicherheits- und Geschäftsregeln passiert hat. Nur published ist für die vorgesehene Zielgruppe zugänglich. Während eines Scans sollte kein Download-Link ausgegeben werden, und „Upload abgeschlossen“ muss von „Inhalt bereit“ getrennt bleiben.
Jeder Übergang muss durch einen autorisierten serverseitigen Vorgang erfolgen. Ein vom Browser gesendetes Feld wie scanPassed oder public darf niemals über die Veröffentlichung entscheiden. Die Oberfläche zeigt nur das Ergebnis einer Systementscheidung.
Autorisierung mit der ersten Anfrage beginnen
Ein Nutzer muss eine Datei nicht immer über den Anwendungsserver senden. Bei großen Dateien oder hohem Traffic kann der Server eine kurzlebige Upload-Berechtigung ausstellen, und der Client lädt direkt in Object Storage. Diese Berechtigung darf keine öffentliche URL sein, die auf einem Dateinamen basiert.
Vor dem Ausstellen sollte der Server mindestens prüfen: Darf dieser Nutzer eine Datei zu dieser Ressource hinzufügen, ist der Zielbereich gültig, liegt die erwartete Größe innerhalb der Richtlinie und welche Inhaltstypen sind erlaubt? Die Berechtigung wird an einen Nutzer, einen servergenerierten Object Key, eine kurze Laufzeit und möglichst Bedingungen wie Content Length gebunden.
Object Keys aus einem nutzereingereichten Dateinamen zu erzeugen, ist ebenfalls riskant. Vorhersehbare Namen können Dateien anderer Nutzer überschreiben oder Zugriffspfade verraten. Eine zufällige serverseitige Kennung sollte getrennt vom Originalnamen gespeichert werden; bei der Anzeige wird ein sicherer Downloadname verwendet.
Uploads in Quarantäne speichern
Nach dem Upload darf die Datei nicht sofort in öffentlichen Speicher oder in den von der Anwendung genutzten Bereich gelangen. Sie wird zuerst in einen getrennten Quarantäneort geschrieben. Dort sollten weder öffentliche URL, CDN-Verteilung noch eine Vorschau für andere Nutzer aktiv sein.
Ein Quarantänedatensatz kann Uploader, Zielressource, Object Key, angegebenen Inhaltstyp, Größe, Prüfsumme und Zeitstempel enthalten. Er ist zugleich Eingabe für den Scan-Job und Beginn einer Ereignisspur. Da auch Metadaten Nutzereingaben enthalten, dürfen sie in Administrationsoberflächen nicht als HTML oder Shell-Kommando interpretiert werden.
Quarantäne vereinfacht auch die Bereinigung nach fehlgeschlagenem Scan. Ein abgelehntes Objekt kann kurz für Audit-Zwecke aufbewahrt und anschließend durch eine Lifecycle-Regel gelöscht werden. Der Hauptspeicher der Anwendung enthält dann nur genehmigte Objekte.
Inhalt auf mehreren Ebenen prüfen
Eine Datei mit .pdf-Endung ist nicht unbedingt ein PDF. Prüfungen sollten mehrschichtig sein:
- Der Client prüft Endung und Größe für schnelles Feedback.
- Der Server wendet Richtlinien für erwarteten Typ und Größe vor der Upload-Berechtigung an.
- Ein Scan-Worker prüft Signaturen oder Magic Bytes.
- Bei Bedarf bestätigt ein formatspezifischer Parser, dass das Dokument wirklich verarbeitet werden kann.
Keine dieser Ebenen ist allein eine vollständige Sicherheitsgrenze. Client-Prüfungen sind leicht zu umgehen, MIME-Header können gefälscht sein und Parser besitzen eigene Angriffsflächen. Parsing und Konvertierung sollten deshalb in Prozessen laufen, die von der Hauptanwendung getrennt sind und begrenzte Ressourcen haben.
Scan asynchron und idempotent machen
Virenscan, Inhaltsmoderation, OCR oder Konvertierung können eine Upload-Anfrage langsam machen. Diese Arbeit innerhalb der Anfrage auszuführen, erzeugt Timeouts und eine schlechte Erfahrung. In einem widerstandsfähigeren Ablauf legt der Quarantänedatensatz einen Job in eine Queue; ein Worker scannt die Datei und schreibt sein Ergebnis atomar in den Dateizustand.
Da Nachrichten erneut zugestellt werden können, muss der Worker idempotent sein. Wird dieselbe Datei zweimal gescannt, darf der zweite Lauf keine weitere Veröffentlichung erzeugen; er muss das bestehende Ergebnis sicher erkennen. Stürzt ein Worker ab oder hat ein externer Scanner einen temporären Fehler, kann der Zustand failed werden und eine kontrollierte Wiederholung folgen. Bei einem Timeout bleibt die Datei sicherheitshalber in Quarantäne.
Nach dem Scan darf nur ein genehmigtes Objekt in dauerhaften privaten Speicher wechseln oder eine neue Zugriffsrichtlinie erhalten. Können Objektverschiebung und Statusupdate auseinanderlaufen, braucht es einen Datensatz und Reparaturjob, der beide Seiten abgleicht.
Download und Vorschau ebenfalls schützen
Mit der Genehmigung endet die Zugriffskontrolle nicht. Beim Download muss erneut geprüft werden, ob der Nutzer die zugehörige Ressource sehen darf. Kurzlebige signierte URLs können berechtigten Nutzern Zugriff auf ein privates Objekt geben, ohne dessen Bytes über den Anwendungsserver zu leiten. Die URLs sollten weiterhin nicht erratbar, nicht unnötig langlebig und auf ein Objekt begrenzt sein.
Besonders sorgfältig ist die Browservorschau von Nutzerinhalten. Aktive Formate wie HTML und SVG, die von der eigenen Anwendungsdomain ausgeliefert werden, können das XSS-Risiko erhöhen. Nicht vertrauenswürdige Inhalte über eine separate Origin auszuliefern, einen Download zu erzwingen oder eine umgewandelte sichere Darstellung zu zeigen, kann besser sein. Header wie Content-Disposition, Content Security Policy und nosniff ergänzen die Verteidigung.
Nutzern den richtigen Status, dem Team die richtigen Signale geben
„Upload fehlgeschlagen“ und „Datei hochgeladen, aber bei Sicherheitsprüfung abgelehnt“ sind nicht dieselbe Nachricht. Nutzer müssen verstehen, was passiert ist, ob Wiederholung sinnvoll ist und wann Unterstützung nötig wird. Bei der Erklärung einer Ablehnung sollten unnötige Details vermieden werden, die Angreifern helfen könnten, Kontrollen zu umgehen.
Zu beobachten sind Upload-Erfolg, Scan-Latenz, Ablehnungsrate, Wiederholungen, Alter der Queue und Speicherfehler. Logs dürfen Object-Kennungen und Operationsergebnisse enthalten, aber niemals Dateiinhalte, geheime URLs oder sensible Dokumenttexte.
Sicherer Datei-Upload ist nicht ein einzelner Antivirus-Aufruf. Autorisierte Annahme, Quarantäne, mehrschichtige Validierung, asynchroner Scan, kontrollierte Veröffentlichung und Zugriffskontrollen wirken zusammen, damit Inhalte einfach geteilt werden können, ohne die Sicherheitsgrenze der Anwendung zu schwächen.