2011-09-06 10 views
12

Sviluppo uno script php per sostituire quello corrente, che avrà molta esposizione a vari mercati/paesi. Questo script tra gli altri offre una funzionalità di caricamento delle foto.Approccio alla sicurezza del caricamento dell'immagine PHP

Dopo aver letto molte informazioni sul problema, ho seguito l'approccio descritto di seguito. Apprezzerei molto i vostri commenti sulla sua sicurezza.

  1. La foto viene caricata in una cartella 777 privata all'esterno di Web Root.
  2. Viene eseguito un controllo per le estensioni elencate in bianco (consenti solo jpg, gif, png) tutto il resto viene eliminato.
  3. Uso di getimagesize per verificare dimensioni min-max e validità foto.
  4. Verifica del mimetype e della corrispondenza dell'estensione di file.
  5. Ridimensionamento della foto caricata su dimensioni std (utilizzando imagecopyresampled).
  6. Salvataggio dei file creati come jpg.
  7. Rimozione del file originale.
  8. Salvare le foto con un nuovo nome (non casuale), ad esempio img51244.jpg.
  9. Spostare le nuove foto in sottodirectory variabili di una cartella pubblica (777 autorizzazioni) in base a un algoritmo non prevedibile. Ad esempio, img10000.jpg verrà archiviato allo photos/a/f/0/img10000.jpg mentre lo img10001.jpg verrà archiviato allo photos/0/9/3/img10001.jpg. Questo viene fatto per altri motivi (uso di sottodomini per contenuto statico o utilizzo di un CDN).

Lo script verrà eseguito su un server dedicato Linux.

+0

niente salta fuori da me qui. a parte il permesso 777 sulla cartella - come ho capito, se ha 777 permessi, non è privato. ma per quanto posso dire questo sarebbe davvero importante se il tuo server fosse compromesso (che non mi sembra verosimile attraverso questo script almeno) – jammypeach

+2

777 non sembra sicuro. Possibile correlato a http://stackoverflow.com/questions/3644138/secure-user-image-upload-capabilities-in-php – ajreal

+0

Mi sembra molto buono, tranne forse per autorizzazioni molto liberali. Forse possono essere un po 'limitati? Altrimenti, questo fa tutto il necessario che riesco a pensare, inclusa la rimozione dei dati EXIF ​​ –

risposta

3

È inoltre necessario controllare la dimensione del file caricato, poiché a volte le immagini ottenute con getimagesize possono superare la memoria RAM disponibile. È inoltre opportuno presumere che lo script possa bloccarsi in qualsiasi momento (ad esempio quando l'elettricità si interrompe), quindi è necessario implementare alcune procedure di pulizia per rimuovere i file non necessari.

+1

Il file massimo caricabile è già limitato in php.ini. – Maerlyn

+0

Sì, ma non significa che sia sufficiente per evitare il superamento del limite di RAM. –

+0

Se supera la dimensione in php.ini non si ottiene un nome di file in '$ _FILES' - quindi non è possibile controllarne la dimensione. – Maerlyn

-1

Questo è un approccio abbastanza completo, ma non vedo alcun meccanismo di prevenzione dell'esecuzione del codice.

È necessario assicurarsi che il contenuto dell'immagine non sia mai incluso (con inclusione o richiesta di chiamata) o eseguito tramite eval().

In caso contrario, il codice php incluso alla fine del file potrebbe essere eseguito.

Si può anche provare a rilevare il codice php all'interno del contenuto dell'immagine (con file_get_contents, e poi una regex ricerca di "<? Php", per esempio), ma non sono riuscito a trovare un modo sicuro al 100% per eliminare il codice sospetto senza distruggere alcune immagini (valide).

+0

Non vedo come il codice PHP verrà eseguito in un file JPG a meno che il server non sia configurato correttamente? –

+0

Non ha senso, poiché è ovvio che nessuno chiamerà eval o includerà sull'immagine. Non riesco a pensare ad uno scenario in cui qualcuno possa mai pensare di farlo (a meno che non abbia appena iniziato a usare PHP). –

+0

Il file originale viene eliminato non appena si verificano le foto ricampionate. viene utilizzato solo con le seguenti funzioni php in questo ordine: move_uploaded_file, filesize, getimagesize, imagecreatefromjpeg, imagecopyresampled. – Alex

4
  1. Una directory con chmod 0777 è, per definizione, pubblica per gli altri utenti collegati al server, non privati. Le autorizzazioni corrette sarebbero 700 e di proprietà di apache (o qualsiasi utente al quale il server web viene eseguito). Non sono sicuro del motivo per cui non utilizzeresti la directory temporanea predefinita di php qui, poiché tende ad essere al di fuori della web root.
  2. Una white-list è una buona idea. Fai attenzione ad avere una corretta implementazione. Ad esempio, la regexp /.png/ corrisponde effettivamente a apng.php.
  3. Questo passaggio è una grande idea. In pratica controlla il file magico.
  4. Non è strettamente necessario. Nei due passaggi precedenti, abbiamo determinato che l'estensione e il formato del file sono corretti. Se è necessario specificare un tipo MIME corretto da specificare dal client, è necessario verificare anche che il tipo MIME specificato e quello determinato sopra siano equivalenti.

I passaggi da 5 a 8 non sono correlati alla sicurezza.

Passaggio 9: presumo che il tuo sito consenta a tutti di vedere ogni foto. In caso contrario, dovresti disporre di uno schema URL con URL sostanzialmente più lunghi (ad esempio, l'hashs dell'immagine).

+1

(-1) 777 non significa pubblico in termini di accessibilità attraverso il web - questo è ciò di cui sta parlando. E il tuo esempio di regex implica che questo è comunque di qualsiasi imortanza ... e BTW exe è un'estensione di Windows ...: -/ – Raffael

+0

@ Raffael1984 Penso che phihag lo sappia. È ancora pubblico in termini di * accessibilità ad altri utenti sullo stesso server web *, che * è * un problema. Ma sono d'accordo che il passaggio 2) non è necessario se lo fai 3) correttamente –

+0

@ Raffael1984 Vero. Non sono sicuro del perché questo passo sia necessario. Aggiornata la risposta. – phihag

Problemi correlati