Ochrana nahrávání souborů v Go: ochrana proti 7 běžným útokům
V systémech bez tradiční autentizace je nahrávání souborů závislé na důvěryhodné identifikaci požadavků. Pro prohlížečové rozšíření PDF-to-Markdown byl implementován model na základě ECDSA P-256 prostřednictvím WebCrypto API. Při prvním spuštění se generuje neexportovatelná klíčová dvojice:
const keyPair = await crypto.subtle.generateKey(
{ name: 'ECDSA', namedCurve: 'P-256' },
false, // extractable = false
['sign', 'verify']
);
Veřejný klíč se zaregistruje na serveru, vrátí se device_id a device_token. Každý API požadavek obsahuje:
Authorization: Bearer <token>X-Timestamp(±5 minut)X-Nonce(proti opakování)X-Body-SHA256X-Signature(ECDSA nad METHOD+PATH+TIMESTAMP+NONCE+BODY_HASH)
Server ověřuje podpis pomocí veřejného klíče. Toto zajišťuje:
- Omezení rychlosti na zařízení
- Ochrana proti replay-útokům
- Kontrola slotů (max. 3 aktivní úlohy)
- Omezení registrací (5/IP/hodina)
Tento model zvyšuje náklady na útok: emulace vyžaduje kompletní implementaci ECDSA podpisů.
Útok 1: Podvržení typu souboru
Útočník maskuje spustitelný soubor jako PDF. Ochrana funguje na třech úrovních.
Frontend: Ověření MIME a přípony:
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: 'PDF pouze' };
}
Backend: Směrování podle Content-Type. Klíčové: Magic bytes:
pdfMagicBytes := "%PDF"
header4 := make([]byte, 4)
_, err := file.Read(header4)
if string(header4) != pdfMagicBytes {
respondError(w, http.StatusBadRequest,
models.ErrCodeValidationError,
"Soubor není platný PDF")
}
file.Seek(0, 0)
Ověření prvních bajtů ignoruje hlavičky i přípony. Polyglot soubory (platné PDF + škodlivý kód) vyžadují další signatury.
Útok 2: Přeplnění disku
DoS útok pomocí velkých souborů. Omezení:
http.MaxBytesReader(w, r.Body, MaxFileSize + 1MB)— přeruší čtení přes limit.- Sloty na zařízení: max. 3 aktivní úlohy (
queued,processing,ready,error). - Omezení rychlosti při registraci i požadavcích.
Identifikace zařízení činí změnu IP nebo tokenu neúčinnou.
Útok 3: Cesta traversal
Útočník používá ../../../etc/passwd. Řešení: Pevné jméno {UUID}/input.pdf. Uživatelský vstup v cestě je plně ignorován.
Sanitace frontendu (doplňková):
function sanitizeFileName(name) {
return name
.replace(/[/\\?%*:|"<>]/g, '-')
.replace(/^\.+/, '')
.replace(/\.+$, '')
.substring(0, 255)
.trim();
}
Backend generuje cestu nezávisle na názvu souboru.
Útok 4: SSRF přes stahování z URL
Pro kanál "stažení z URL" jsou blokovány:
- DNS resoluce před stažením
- Přesměrování
- Soukromé IP adresy (denylist: 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16)
Útok 5: Replay-útoky
X-Nonce + X-Timestamp + podpis. Nonce je uložen na zařízení, timestamp má okno ±5 minut.
Útok 6: Podvržení zařízení
extractable: false zabraňuje vývozu privátního klíče. Ukradení device_token je bezúčelné bez podpisu.
Útok 7: Zneužití na úrovni aplikace
Omezení rychlosti + sloty + podpis. Max. 3 sloty, 5 registrací/IP/hodina.
Co je důležité
- Kryptografická identifikace na zařízení nahrazuje účty pro omezení.
- Magic bytes (
%PDF) jsou jediná spolehlivá kontrola typu souboru. MaxBytesReader+ sloty chrání proti DoS.- Fixní cesty vylučují traversal.
- ECDSA P-256 + nonce/timestamp blokuje replay a podvržení.
— Editorial Team
Zatím žádné komentáře.