Penso che l'unico modo per rispondere a questa domanda sia attraverso uno sforzo di commento collaborativo, quindi ecco un wiki della comunità:
- Of course only registered users can upload, but I know that doesn't mean anything.
D'accordo.
- The site is exposed via nginx.
Il che significa che hai l'effettiva applicazione web in esecuzione dietro di te - assicurati che la tua scheda (WSGI? fCGI?) sia impostata in modo sicuro.
- The machine on which the webserver is hosted only accepts incoming connections from the nginx machine.
mossa intelligente!
- The image upload link (nginx directive) is rate limited (in a way that generously accounts for a legitimate user spike).
Assicurati che questo non lo renda più facile a DoS-attack del tuo sito.
- The webserver accepts only jpg/png/tiff/webp image formats (it derives the mime type using the magic library).
magemagick è una libreria molto ben mantenuta, ma è anche una superficie di attacco molto grande e ci sono state molte violazioni critiche. Utilizzare una libreria molto più ristretta per la convalida potrebbe essere una buona scelta.
assicurati che l'estensione di file caricata corrisponda sempre al formato rilevato e che il file possa essere decodificato correttamente come tale. Puoi anche prendere in considerazione la possibilità di rimuovere vari metadati, come i tag EXIF, in pratica aggiungere una fase di elaborazione, che accetta solo quanto necessario (solo dati immagine) e salva come nuovo file, con questo passaggio eseguito il più isolato possibile (quindi RCE nell'immagine le librerie di decodifica non danno accesso a nessuno dei malintenzionati). Dopo questo, assicurati che nginx risponda sempre con il Content-Type corretto e tutte le intestazioni di sicurezza, X-Content-Type-Options ecc.
- Both nginx and the webserver have a limit on the accepted file size.
bene.
- All uploaded files are saved using a filename which is a hash of the contents.
Assicurati di salare quell'hash; gli hash sono fendibili (entro i limiti) e non vuoi che un attaccante controlli il nome del file dei loro caricamenti. Non usare solo MD5, ma un hash meno rotto.
- By default, they are saved with only rw permissions, not rwx.
Salvali con le autorizzazioni di lettura. Una volta salvati, non devono mai essere modificati di nuovo.
Inoltre, usa SELinux (o l'equivalente del tuo server OS) per assicurarti che la tua applicazione web possa solo scrivere e leggere quella directory, non eseguire mai file in essa.
- The images are stored on the same system as the webserver.
Potrebbe presto diventare un problema di scalabilità: il software del server dovrebbe preferibilmente funzionare su supporti di archiviazione veloci e affidabili (SSD con hot fallover), mentre le immagini dell'utente sarebbero sufficientemente memorizzate su supporti di archiviazione economici con backup lenti (ad esempio se due le unità si guastano nello stesso momento, OK, occorrono 15 minuti per ripristinare la ridondanza e potrebbero perdere un paio di minuti di nuove immagini utente.
They are saved directly to the final location (there's no intermediate staging location) but the images are not available for viewing until a specific database column is updated (see next point).
A periodic virus scan is completed on the newly uploaded files (and any malicious files are removed to a different directory to which the servers have no access) and then the aforementioned database column is updated to make the files available for viewing.
Non c'è alcun vantaggio computazionale a farlo periodicamente invece che istantaneamente dopo aver caricato il file. Quindi, fallo istantaneamente e mantieni il carico di archiviazione il più costante possibile. L'esecuzione dell'antivirus come demone evita di dover caricare le definizioni dei virus in memoria per ogni scansione.
- Lastly, a tiny amount of random noise is added to each image by doing something like
magick image.jpg -evaluate Add 0.1 image.jpg
Questo è un passaggio intenso di elaborazione molto , che decomprime le immagini, aggiunge rumore e questa è la parte peggiore, che in caso di JPEG porta alla massima perdita di qualità se si desidera mantenere la dimensione del file originale . (il rumore è molto difficile da comprimere, a meno che non sia così debole da essere effettivamente compresso e l'immagine risultante sia effettivamente come se non si aggiungessero mai dei disturbi.)
Non vedo alcun vantaggio in termini di sicurezza in questo passaggio.
Altri punti
- Containerizza la tua applicazione web.
- Utilizza un server di registrazione separato
- Monitora improvvisi aumenti del consumo di spazio di archiviazione, nel caso in cui qualcuno abusasse del tuo sito automaticamente, ad es. per ospitare immagini per il proprio guadagno