Sicurezza del caricamento di file in webapp - panoramica della configurazione

2

Per una webapp basata su foto caricate dagli utenti, voglio verificare che sto facendo le cose in modo sufficientemente sicuro. Di seguito è riportato uno schema della configurazione corrente.

  1. Naturalmente solo gli utenti registrati possono caricare, ma so che questo non significa nulla.
  2. Il sito è esposto tramite nginx.
  3. La macchina su cui è ospitato il server Web accetta solo connessioni in entrata dalla macchina nginx.
  4. Il link di caricamento dell'immagine (direttiva nginx) è a tasso limitato (in un modo che genera generosamente un picco di utenti legittimi).
  5. Il webserver accetta solo i formati di immagine jpg / png / tiff / webp (ricava il tipo mime usando la libreria magica).
  6. Sia nginx che il server web hanno un limite alle dimensioni del file accettato.
  7. Tutti i file caricati vengono salvati usando un nome file che è un hash dei contenuti.
  8. Per impostazione predefinita, vengono salvati con le sole autorizzazioni rw, non con rwx.
  9. Le immagini sono memorizzate sullo stesso sistema del server web.
  10. Vengono salvati direttamente nella posizione finale (non esiste una posizione di staging intermedia) ma le immagini non sono disponibili per la visualizzazione fino a quando non viene aggiornata una colonna di database specifica (vedere il prossimo punto).
  11. Una scansione periodica dei virus viene completata sui file appena caricati (e tutti i file dannosi vengono rimossi in una directory diversa a cui i server non hanno accesso) e quindi la colonna di database sopra menzionata viene aggiornata per rendere i file disponibili per la visualizzazione.
  12. Infine, una piccola quantità di rumore casuale viene aggiunta a ciascuna immagine facendo qualcosa come magick image.jpg -evaluate Add 0.1 image.jpg

Quali vettori mi mancano? L'obiettivo non è quello di proteggere contro un attore statale, ma di avere una protezione ragionevole contro l'irritante malevolo medio (o anche piuttosto abile).

    
posta Yogesch 10.06.2018 - 21:27
fonte

1 risposta

4

Penso che l'unico modo per rispondere a questa domanda sia attraverso uno sforzo di commento collaborativo, quindi ecco un wiki della comunità:

  1. Of course only registered users can upload, but I know that doesn't mean anything.

D'accordo.

  1. 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.

  1. The machine on which the webserver is hosted only accepts incoming connections from the nginx machine.

mossa intelligente!

  1. 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.

  1. 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.

  1. Both nginx and the webserver have a limit on the accepted file size.

bene.

  1. 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.

  1. 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.

  1. 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.

  1. 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).

  2. 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.

  1. 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

  1. Containerizza la tua applicazione web.
  2. Utilizza un server di registrazione separato
  3. 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
risposta data 10.06.2018 - 22:46
fonte

Leggi altre domande sui tag