2010-09-04 7 views
10

Sto implementando uno strumento di caricamento immagini basato sull'utente per il mio sito web. Il sistema dovrebbe consentire a tutti gli utenti di caricare solo file JPEG e PNG. Sono, ovviamente, preoccupato per la sicurezza e quindi mi chiedo come le persone più intelligenti di me pensano ai seguenti controlli per consentire i caricamenti:Funzionalità di caricamento immagini utente sicuro in PHP

1) Primo elenco bianco le estensioni di file consentite in PHP per consentire solo PNG, png, jpg, JPG e JPEG. Recuperare l'estensione del file dell'utente tramite una funzione come ad esempio:

return end(explode(".", $filename)); 

Questo dovrebbe aiutare a non consentire all'utente di caricare qualcosa di dannoso come .png.php. Passare al punto 2.

2) Eseguire la funzione php getimageize() sul file TMP. Via qualcosa come:

getimagesize($_FILES['userfile']['tmp_name']); 

Se questo non restituisce falso, procedere.

3) Assicurare un file .htaccess viene posto all'interno della directory upload in modo che tutti i file all'interno di questa directory non può analizzare i file PHP:

php_admin_value engine Off 

4) Rinominare file dell'utente a qualcosa di pre-determinato. OSSIA

$filename = 'some_pre_determined_unique_value' . $the_file_extension; 

Ciò consentirà anche di evitare l'iniezione SQL poiché il nome file sarà l'unica variabile determinata dall'utente in tutte le query utilizzate.

Se eseguo quanto sopra, quanto sono vulnerabile per l'attacco sono ancora? Prima di accettare un file dovrei avere 1) permesso solo jpg e png, 2) verificato che PHP dice che è un'immagine valida, 3) disabilitato la directory in cui si trovano le immagini dall'esecuzione dei file .php e 4) rinominato il file degli utenti in qualcosa unico.

Grazie,

+0

Si può usare strip_tags su un file immagine per rimuovere i tag PHP? –

risposta

20

Per quanto riguarda i nomi dei file, nomi casuali sono sicuramente una buona idea e portare via un sacco di mal di testa.

Se si desidera accertarsi che il contenuto sia pulito, valutare l'utilizzo di GD o ImageMagick per copiare l'immagine in entrata 1: 1 in una nuova, vuota.

Ciò diminuisce leggermente la qualità dell'immagine perché il contenuto viene compresso due volte, ma rimuoverà qualsiasi informazione EXIF ​​presente nell'immagine originale. Spesso gli utenti non sono nemmeno consapevoli di quante informazioni vengano inserite nella sezione Metadati dei file JPG! Informazioni sulla telecamera, posizione, orari, software utilizzato ... È buona norma che i siti che ospitano le immagini rimuovano tali informazioni per l'utente.

Inoltre, la copia dell'immagine probabilmente eliminerà la maggior parte degli exploit che utilizzano dati di immagine difettosi per causare overflow nel software di visualizzazione e immettere codice dannoso. Tali immagini manipolate probabilmente si riveleranno illeggibili per GD.

+6

Ottima risposta. Devo solo aggiungere che come difesa aggiuntiva, servi le immagini da un dominio throw-away diverso dal dominio in cui imposti i cookie. In questo modo, anche l'immagine ha in qualche modo codice lato client eseguibile, la stessa politica di origine del browser eviterà molti danni. –

+0

@sar ottima idea, non ci ho pensato! –

+0

@SripathiKrishnan come configurare un dominio di eliminazione per immagini ... qualsiasi riferimento ... per la risposta – sid

1

Tutti i controlli sembrano buoni, il numero 3 in particolare. Se le prestazioni non sono un problema, o lo fai in background, puoi provare ad accedere all'immagine usando GD e vedere se è davvero un'immagine e non solo un mucchio di schifezze che qualcuno sta cercando di riempire il tuo server con.

4

Per quanto riguarda il numero 2), non controllare solo per FALSE. getimagesize restituirà anche il tipo mime dell'immagine.Questo è di gran lunga un modo più sicuro per verificare il corretto tipo di immagine rispetto al tipo MIME fornito dal cliente:

$info = getimagesize($_FILES['userfile']['tmp_name']); 
if ($info === FALSE) { 
    die("Couldn't read image"); 
} 
if (($info[2] !== IMAGETYPE_PNG) && ($info[2] !== IMAGETYPE_JPEG)) { 
    die("Not a JPEG or PNG"); 
} 
+0

+1 perso uno "però (die riga di comando 3) . – Thomas

+0

woops.una buona cattura risposta risolta, e grazie –

+1

è possibile che un file sia valido gif e contenga il codice php allo stesso tempo, quindi getimagesize() ha vinto Dare molta protezione reale – Stann

Problemi correlati