Sichere Dateiuploads in Go: Abwehr von 7 gängigen Angriffen
In Systemen ohne klassische Authentifizierung sind robuste Mechanismen zur Identifikation der Anfragende notwendig. Für eine Browser-Erweiterung, die PDFs in Markdown konvertiert, wird ein ECDSA-P-256-basierter Ansatz mit der WebCrypto-API implementiert. Beim ersten Start wird ein nicht exportierbares Schlüsselpaar generiert:
const keyPair = await crypto.subtle.generateKey(
{ name: 'ECDSA', namedCurve: 'P-256' },
false, // extractable = false
['sign', 'verify']
);
Der öffentliche Schlüssel wird auf dem Server registriert und liefert einen device_id sowie einen device_token. Jeder API-Aufruf enthält:
Authorization: Bearer <token>X-Timestamp(±5 Minuten)X-Nonce(Anti-Replay)X-Body-SHA256X-Signature(ECDSA-Signatur über METHOD+PATH+TIMESTAMP+NONCE+BODY_HASH)
Der Server verifiziert die Signatur mit dem öffentlichen Schlüssel und gewährleistet so:
- Rate-Limiting pro Gerät
- Schutz vor Replay-Angriffen
- Slot-Steuerung (max. 3 aktive Aufgaben)
- Registrierungsbeschränkungen (5/IP/Stunde)
Dieser Ansatz erhöht den Angriffsaufwand – eine Emulation erfordert eine vollständige Implementierung von ECDSA.
Angriff 1: Dateityp-Spoofing
Ein Angreifer verschleiert eine ausführbare Datei als PDF. Die Abwehr erfolgt auf drei Ebenen.
Frontend: MIME-Typ und Erweiterungsprüfung:
const ALLOWED_TYPES = ['application/pdf'];
const ALLOWED_EXTENSIONS = ['.pdf'];
function validateFile(file) {
const isPdf = ALLOWED_TYPES.includes(file.type) ||
ALLOWED_EXTENSIONS.some(ext =>
file.name.toLowerCase().endsWith(ext));
if (!isPdf) return { valid: false, error: 'Nur PDF' };
}
Backend: Route basierend auf Content-Type. Kritisch: Magic Bytes:
pdfMagicBytes := "%PDF"
header4 := make([]byte, 4)
_, err := file.Read(header4)
if string(header4) != pdfMagicBytes {
respondError(w, http.StatusBadRequest,
models.ErrCodeValidationError,
"Datei ist kein gültiges PDF")
}
file.Seek(0, 0)
Die Prüfung der ersten Bytes umgeht Header und Erweiterungen. Polyglot-Dateien (gültige PDFs mit schädlichem Inhalt) erfordern zusätzliche Signaturen.
Angriff 2: Disk Exhaustion (DoS)
Denial-of-Service durch große Dateien. Gegenmaßnahmen:
http.MaxBytesReader(w, r.Body, MaxFileSize + 1MB)– Stoppt das Lesen bei Grenze.- Gerätebasierte Slots: max. 3 aktive Aufgaben (
queued,processing,ready,error). - Rate-Limits bei Registrierung und Anfragen.
Geräteidentifikation macht IP- oder Token-Rotation wirkungslos.
Angriff 3: Pfad-Traversal
Ein Angreifer nutzt ../../../etc/passwd. Lösung: Fester Pfad {UUID}/input.pdf. Benutzereingaben in Pfaden werden komplett ignoriert.
Frontend-Sanitisierung (zusätzliche Schicht):
function sanitizeFileName(name) {
return name
.replace(/[/\\?%*:|"<>]/g, '-')
.replace(/^\.+/, '')
.replace(/\.$/, '')
.substring(0, 255)
.trim();
}
Backend generiert den Pfad unabhängig vom Dateinamen.
Angriff 4: SSRF über URL-Upload
Für die Funktion „Upload per URL“ werden folgende Maßnahmen blockiert:
- DNS-Auflösung vor Download
- Umleitungen
- Private IPs (verboten: 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16)
Angriff 5: Replay-Angriffe
X-Nonce + X-Timestamp + Signatur. Nonce wird pro Gerät gespeichert; Timestamp wird innerhalb ±5 Minuten validiert.
Angriff 6: Geräte-Imitation
extractable: false stellt sicher, dass der private Schlüssel nicht exportiert werden kann. Das Stelen von device_token ist nutzlos ohne gültige Signaturen.
Angriff 7: Anwendungsebene Missbrauch
Rate-Limits + Slot-Steuerung + kryptografische Signatur. Max. 3 Slots, 5 Registrierungen/IP/Stunde.
Wichtige Erkenntnisse
- Kryptografische Geräteidentifikation ersetzt Konten für Rate-Limiting.
- Magic Bytes (
%PDF) sind die einzige zuverlässige Methode zur Überprüfung des Dateityps. MaxBytesReader+ Slot-Management verhindern DoS.- Feste Pfade eliminieren Traversal-Risiken.
- ECDSA P-256 mit Nonce/Timestamp blockiert Replay und Imitation.
— Editorial Team
Noch keine Kommentare.