Ho fatto abbastanza per non essere compromesso attraverso il caricamento delle immagini

1

So che non puoi mai essere sicuro di aver fatto abbastanza per essere sicuro, e so anche che il caricamento dei file è difficile da correggere. Prima di fare questa domanda ho letto alcuni dei post correlati qui come rischio di caricamento di immagini php , Quali passaggi devono essere adottati per convalidare ... e rischi per la sicurezza del caricamento .

Quindi penso di aver fatto tutto il necessario, ma sarei molto grato se qualcuno potesse dare un'occhiata a quello che ho e dire se ho fatto abbastanza. Quindi sto eseguendo l'ultimo PHP 5.5.9-1+sury.org~saucy+1 su Apache/2.4.7 . E il mio metodo di caricamento è il seguente:

public static function uploadTemp($number, $file){
    //check if the filename exist and upload was without an error
    if (!$file['name'] || $file['error']){
        return false;
    }

    // check if extension is valid
    if (!Helper::validExtension($file['name'])){
        return false;
    }

    // check is the size of file is valid
    if ($file['size'] > (1024 * 1024 * 6) || $file['size'] < 1024 * 10){
        return false;
    }

    // no need to upload images less than 50x50. Also $file['size'] can be spoofed
    $imageSize = getimagesize($file['tmp_name']);
    if ($imageSize === false || $imageSize[0] < 50 || $imageSize[1] < 50){
        return false;
    }

    require_once('SimpleImage.php');
    $image = new SimpleImage();
    $image->load($file['tmp_name']);

    // saving a file to a temporary directory and renaming it.
    $image->save(Image::$tempDir.$number.'.jpg');
    return true;
}

SimpleImage è uno strumento open source per manipolare un'immagine , all'interno di uno strumento ho cambiato solo una cosa (funzione salva per salvare ogni file con permessi 644 ). Il mio $number è una stringa che è una concatenazione di numeri casuali e un timestamp corrente, $file = $_FILES['fileToUpload'] e validExtension guarda nel seguente modo:

public static function validExtension($filename){
    $extensions = array('jpg', 'jpeg', 'png');

    $arr = explode('.', $filename);
    if ( in_array(strtolower(end($arr)), $extensions) ){
        return true;
    } else return false;
}

La mia cartella temporanea ha 755 permessi.

Quindi la mia domanda è: mi manca qualcosa qui o c'è modo in cui posso migliorare le cose:

  • potrebbe limitare ulteriori permessi (non ho bisogno di fare nulla con le immagini se non di vederle dal client. La cartella è usata solo per il caricamento delle immagini)
  • potrebbe cambiare alcuni parametri in php.ini o apache
posta Salvador Dali 06.03.2014 - 12:22
fonte

1 risposta

6
// check if extension is valid

è in gran parte inutile. Tu (saggiamente) crei il nome del filesystem senza alcun input dal nome del file originale, quindi l'estensione viene scartata comunque.

Le estensioni dei nomi di file non sono una convenzione osservata globalmente. Anche su Windows non tutti usano le stesse mappature delle estensioni di file. Quindi di solito non è consigliabile fare affidamento su determinate estensioni.

// no need to upload images less than 50x50

Dovrai controllare che le dimensioni dell'immagine non siano troppo grandi. Il caricamento di un'immagine enorme (specialmente di una sovra-compressa) è un buon modo per eseguire un server DoS.

My temporary folder has 755 permissions.

Idealmente vorrai avere l'utente del server web e l'utente del proprietario del file in un gruppo, in modo che tu possa dargli 750 permessi, permettendo all'utente web di scrivere file senza dare gli stessi privilegi a nessun altro utente sul server.

I changed only one thing (function save to save every file with 644 permissions)

E allo stesso modo 640 qui, o più probabilmente 660 se vuoi che il tuo utente proprietario sia in grado di scrivere sui file dell'utente del server web.

The folder is used only for image uploading

Assicurati di applicarlo a livello di server, in modo che se qualcuno fa riesca a caricare un file .php o .htaccess in quella directory, non fa nulla. Non sembra che questo codice lo consenta, ma potrebbe esserci qualche altro difetto da qualche parte.

In generale, ogni file / directory che è scrivibile per l'utente del server web deve essere reso completamente non eseguibile, bloccando il server web per fare solo il file statico che serve da lì, o non servire nulla da lì a tutti .

Se sei che il server web fornisce l'immagine fuori dalla directory di caricamento, hai una serie di potenziali problemi di cross-site-scripting:

  • IE annusa il contenuto del file per trovare l'HTML incorporato e trattarlo come una pagina Web (con script) - può essere prevenuto in versioni più aggiornate utilizzando X-Content-Type-Options header;
  • Java considera il file come un'applet, ignorando il tipo reale; Flash considera il file come un file SWF, ignorando il tipo reale; le stesse politiche di origine di questi plugin non corrispondenti a JavaScript;
  • Flash loadPolicyFile che considera il file come un file di criteri su più domini, ignorando il tipo reale e, nelle versioni precedenti di Flash, il contenuto non valido.

Hai notevolmente mitigato questi attacchi con contenuti XSS caricando e ri-salvando l'immagine come JPEG, il che avrebbe disturbato il contenuto del file, quindi un utente malintenzionato non può semplicemente includere il contenuto attivo così com'è all'interno del file .

Non è totalmente impossibile per un utente malintenzionato inviare un'immagine che sa, quando il PHP lo salva nuovamente, comporterà la selezione di contenuti dannosi visualizzati da qualche parte nel file. Questo sarebbe piuttosto difficile, specialmente per un encoder lossy come JPEG, e non ho sentito nessuno che lo abbia mai usato in un attacco reale, ma è concepibile. Il formato JPEG non è specificamente progettato per fornire garanzie rigide sulla difficoltà di creare input per generare un output scelto (come un hash crittografico).

Se vuoi essere sicuro non ci sono possibili attacchi di upload XSS la solita soluzione è quella di servire i tuoi file di dati non attendibili da un dominio separato, in modo che lo scripting cross-site in esso non porta l'attaccante nel tuo sito principale.

    
risposta data 06.03.2014 - 17:43
fonte