[PHP] upload di file in cartella e sua sicurezza

marino51

Utente Attivo
28 Feb 2013
3.204
207
63
Lombardia
@borgo italia
un paio di esempi,

caso 1

Upload : PNG.txt
Type : text/plain ------------------------------ restituito dal browser ie11
Size (kB) : 42.76953125
Stored in : C:\Windows\Temp\php87A2.tmp
target folder : C:/Web_Sites/__Test/PHP/TEST/_xnotar/
target file : C:/Web_Sites/__Test/PHP/TEST/_xnotar/PNG.txt
MIME TYPE : image/png -------------------------- restituito dalla funzione php
Il file -- PNG.txt -- è stato caricato correttamente.
( che sia stato caricato come txt non è proprio giusto e sarà necessario decidere cosa fare )

caso 2

Upload : txt.jpg
Type : text/plain ------------------------------ restituito dal browser ie11
Size (kB) : 4.3974609375
Stored in : C:\Windows\Temp\php2A67.tmp
target folder : C:/Web_Sites/__Test/PHP/TEST/_xnotar/
target file : C:/Web_Sites/__Test/PHP/TEST/_xnotar/txt.jpg
MIME TYPE : text/x-php -------------------------- restituito dalla funzione php
ERRORE : Il file non è del tipo corretto.

ma sembra che il browser non sia perfetto ....
 

borgo italia

Super Moderatore
Membro dello Staff
SUPER MOD
MOD
4 Feb 2008
16.046
150
63
PR
www.borgo-italia.it
ciao @marino51
guarda che
$mime_type_tmp = mime_content_type($_FILES["fileToUpload"]["tmp_name"]);
è php e dove altrimenti va a leggere le info?
un pinco_pallo qualsiasi per usare la pagina per allegare i documenti usando il sito di xnotar deve usare un bw, quindi a php legge le info che quel bw trasmette
 

marino51

Utente Attivo
28 Feb 2013
3.204
207
63
Lombardia
ciao Gianni (@borgo italia),
ti seguo poco, e quindi provo a spiegare il mio pensiero,

obiettivo, identificare il tipo di file non usando l'informazione proveniente dal browser
PHP:
$file_type = strtolower($_FILES['fileToUpload']['type']); // mime type dal browser

di conseguenza, ho usato nello script l'informazione restituita da "finfo" o in alternativa da "mime_content_type"
per questa seconda, il manuale recita, "Detect MIME Content-type for a file"
non ha quindi nessuna attinenza con l'upload ovvero non recupera l'informazione del browser ma la determina analizzando il file (vedi la differenza negli esempi in un post appena sopra)

detto ciò, sarà probabilmente necessario aggiungere anche il controllo sull'estensione del file per evitare che qualche burlone si diverta a caricare "stupidate" modificando le estensioni, ma ... passo successivo, per ora è sufficiente che le due funzioni php restituiscano correttamente il risultato del loro lavoro su un sistema Linux (del quale non ho disponibilità e quindi devo attendere il risultato delle prove)
 
Ultima modifica:

xnotar

Utente Attivo
3 Apr 2012
65
0
6
Ho fatto alcune prove con l'ultimo script che hai postato.
I jpg, vengono correttamente caricati da tutti e tre i browser, anche se gli cambio estensione esempio LOGO_WEB.jpg se lo cambio in .php lo carica.
Il browser lo invia come application/x-php ma php riconosce il mime-type come image/jpeg
Upload : LOGO_WEB.php
Type : application/x-php
Size (kB) : 105.3759765625
Stored in : /tmp/phpXSbkeO
target folder : models/
target file : models/LOGO_WEB.php
MIME TYPE : image/jpeg
Il file -- LOGO_WEB.php -- è stato caricato correttamente.
mentre il test2.php camuffato in .jpg non viene caricato perché riconosciuto da php come text/plain
Upload : test2.jpg
Type : image/jpeg
Size (kB) : 0.81640625
Stored in : /tmp/phpnx0VmB
target folder : models/
target file : models/test2.jpg
MIME TYPE : text/plain
ERRORE : Il file non è del tipo corretto.
Per quanto riguarda i file stl, non vengono caricati. Php riconosce application/octet-stream
Upload : cubo.stl
Type : application/sla
Size (kB) : 0.66796875
Stored in : /tmp/phpW7OFSN
target folder : models/
target file : models/cubo.stl
MIME TYPE : application/octet-stream
ERRORE : Il file non è del tipo corretto.
per quanto riguarda gli spazi contenuti nei nomi dei file, vengono correttamente identificati e viene mostrato l'errore prima della verifica del MIME
Upload : LOGO WEB.jpg
Type : image/jpeg
Size (kB) : 105.3759765625
Stored in : /tmp/phpn9idd6
target folder : models/
target file : models/LOGO WEB.jpg
ERRORE : Il nome del file intercalato da spazi non è accettato. Rinomina il tuo file!
 

borgo italia

Super Moderatore
Membro dello Staff
SUPER MOD
MOD
4 Feb 2008
16.046
150
63
PR
www.borgo-italia.it
ciao
per il controllo anche dell'estenzione sono d'accordo infatti avevo messo giu uno schema
PHP:
<?php
if(isset($_POST['invia'])){
    echo "<pre>";
    $mime_type_tmp = mime_content_type($_FILES["fileToUpload"]["tmp_name"]);
    var_dump($mime_type_tmp);
    $mime_type = mime_content_type($_FILES["fileToUpload"]["tmp_name"]);
    var_dump($mime_type);
    $nome_file=$_FILES["fileToUpload"]["name"];
    var_dump($nome_file);
    $est=strtolower(pathinfo($_FILES["fileToUpload"]["name"], PATHINFO_EXTENSION));
    var_dump($est);
/*   output
string(13) "image/vnd.dwg"
string(13) "image/vnd.dwg"
string(9) "bagno.dwg"
string(3) "dwg"
bagno.dwg tipo consentito

string(9) "image/png"
string(9) "image/png"
string(15) "logoscritta.png"
string(3) "png"
logoscritta.png tipo consentito

*/
    $mime=array('image/vnd.dwg','image/png');//ecc.....
    $tipo=array('dwg','png');//ecc.....
    if(in_array($mime_type_tmp, $mime) && in_array($est, $tipo)){
        echo "$nome_file tipo consentito<br>";
    }else{
        echo "$nome_file tipo NON consentito<br>";
    }
}
?>
<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" enctype="multipart/form-data">
<input name="fileToUpload" type="file">
<input name="invia" type="submit">
</form>
per il primo non molto in quanto tu leggi i vari $_FILES["fileToUpload"][".........."] che comunque sono filtrati/richiamati dal bw
 

marino51

Utente Attivo
28 Feb 2013
3.204
207
63
Lombardia
per il primo non molto in quanto tu leggi i vari $_FILES["fileToUpload"][".........."] che comunque sono filtrati/richiamati dal bw[/QUOTE]
intendiamoci,
viene letto il file caricato, nello specifico il suo contenuto, nulla a che fare con il browser

se poi intendi $_FILE, si andranno inserite le "validation"
 
Ultima modifica:

borgo italia

Super Moderatore
Membro dello Staff
SUPER MOD
MOD
4 Feb 2008
16.046
150
63
PR
www.borgo-italia.it
ciao
dimenticavo, i controlli possono diventare tre
PHP:
//.....
$type_tmp = $_FILES["fileToUpload"]["type"];
$mime_type_tmp = mime_content_type($_FILES["fileToUpload"]["tmp_name"]);
$est=strtolower(pathinfo($_FILES["fileToUpload"]["name"], PATHINFO_EXTENSION));
//costruire tre array e metterli nell'if
if(in_array($type_tmp, $type) && in_array($mime_type_tmp, $mime) && in_array($est, $tipo)){
    //eccc...   
}
//....
 

marino51

Utente Attivo
28 Feb 2013
3.204
207
63
Lombardia
LOGO_WEB.php, non ho altre idee se non controllare l'estensione e rifiutare il file
si potrebbe modificare l'array "allow..." mettendo l'estensione come chiave ed il tipo atteso come valore in modo da fare il controllo incrociato

test2.jpg, ok è ciò che si vuole

cubo.stl, purtroppo sembra che le funzioni php non riconoscano il file, "application/octet-stream" è un valore "generico"
potrebbe avere un senso l'estensione dell'array come detto sopra ma comunque è parzialmente una "porta aperta"
credo sia inutile usare la definizione del browser che forse la ricava dall'estensione

Il nome del file intercalato da spazi non è accettato. Rinomina il tuo file!, credo vada bene lasciare il controllo

se concordi provo ad inserire la variazione sull'array
 

xnotar

Utente Attivo
3 Apr 2012
65
0
6
Beh se anche qualcuno caricasse un jpg camuffato da php, per la sicurezza non credo sia un problema (almeno credo) con un file jpg cosa ci potrebbero fare?
 

marino51

Utente Attivo
28 Feb 2013
3.204
207
63
Lombardia
Si ma per quello anche in un'immagine vera potrebbero nascondere del codice maligno
ma le funzioni php dovrebbero accorgersi

il codice che segue lega l'estensione con il mime di php, secondo me, aumentando la sicurezza, fai la prova con quelli già definiti, poi andranno aggiunti le altre estensioni con il relativo mime restituito dalle funzioni di php
PHP:
function GestisciUpload($file_path = "models/")
{
    $allowed_type = array
    (
        'stl'   => 'application/octet-stream',
        'gif'   => 'image/gif',
        'jpeg'  => 'image/jpeg',
        'pjpeg' => 'image/pjpeg',
        'png'   => 'image/png',
//        'application/acad',
//        'application/dxf',
//        'application/iges',
//        'application/sla',
//        'application/vnd.ms-pki.stl',
//        'application/x-navistyle',
//        'image/vnd.dwg',
//        'image/x-dwg',
//        'model/iges',
//        'x-world/x-3dmf',
    );

    $UploadErrors = array
    (
        'There is no error, the file uploaded with success',
        'The uploaded file exceeds the upload_max_filesize directive in php.ini',
        'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form',
        'The uploaded file was only partially uploaded',
        'No file was uploaded',
        'Missing a temporary folder',
        'Failed to write file to disk',
        'A PHP extension stopped the file upload. PHP does not provide a way to ascertain which extension caused the file upload to stop; examining the list of loaded extensions with phpinfo() may help',
    );

    $err = $_FILES['fileToUpload']['error'];
    if ($err > 0 )
    {
        echo "ERRORE : ".( $err < 8 ? $UploadErrors[$err] : $err )."<br /><br />";
        return false;
    }

    // controllo se esiste la cartella di destinazione
    if ( !is_dir($file_path) )
    {
        echo "ERRORE : La cartella di destinazione non esiste<br /><br />";
        return false;
    }

    $file_name = $_FILES["fileToUpload"]["name"];             // nome originale del file ( Linux Unix : attenzione maiuscole e minuscole )
    $file_ext  = pathinfo($file_name, PATHINFO_EXTENSION);    // estensione del file caricato
    $file_type = strtolower($_FILES['fileToUpload']['type']); // mime type dal browser
    $file_size = $_FILES['fileToUpload']['size'] / 1024;      // dimensione in kB
    $file_temp = $_FILES['fileToUpload']['tmp_name'];         // file temporaneo, path e nome assegnato dall'upload
    $file      = $file_path.$file_name;                       // path di destinazione e nome originale del file

    // visualizzazioni da eliminare (commentare) in produzione
    echo "Upload : "        .$file_name."<br />";
    echo "extension : "     .$file_ext ."<br />";
    echo "Type : "          .$file_type."<br />";
    echo "Size (kB) : "     .$file_size."<br />";
    echo "Stored in : "     .$file_temp."<br />";
    echo "target folder : " .$file_path."<br />";
    echo "target file : "   .$file     ."<br />";

    // evito nomi di files con spazi intercalati
    if ( substr_count($file_name, ' ') )
    {
        echo "ERRORE : Il nome del file intercalato da spazi non &egrave; accettato. Rinomina il tuo file!<br /><br />";
        return false;
    }

    // controllo se posso ottenere "mime_type"
    if ( class_exists('finfo') )
    {
        $mime_type = ( new finfo(FILEINFO_MIME_TYPE) )->buffer( file_get_contents($file_temp) );
    }
    else if ( function_exists('mime_content_type') )
    {
        $mime_type = mime_content_type($file_temp);
    }
    else
    {
        echo "ERRORE : non posso ottenere 'mime_type' mancano gli strumenti php<br /><br />";
        return false;
    }
    $mime_type = strtolower($mime_type);     // per avere facilità nella gestione dell'array "allowed_type" ammesso ci siano maiuscole
    echo "MIME TYPE : ".$mime_type."<br />";

    // controllo se è accettabile
    if ( empty($allowed_type[$file_ext]) or $mime_type != $allowed_type[$file_ext] )
    {
        echo "ERRORE : Il file non &egrave; del tipo corretto.<br /><br />";
        return false;
    }

    // controllo la dimensione
    if ($file_size == 0)
    {
        echo "ERRORE : Il file &egrave; vuoto.<br /><br />";
        return false;
    }
    if ($file_size > 5000)
    {
        echo "ERRORE : Il file ha una dimensione troppo grande. Carica un file che non superi i 5 Mb.<br /><br />";
        return false;
    }

    // controllo se esiste lo stesso nome
    if ( file_exists($file) )
    {
        echo "ERRORE : Il nome scelto per il file esiste gi&agrave;. Rinomina il tuo file!<br /><br />";
        return false;
    }

    // sposto il file nella destinazione
    if ( !move_uploaded_file($file_temp, $file) )
    {
        echo "ERRORE : Lo spostamento del file nella destinazione non &egrave; riuscito"."<br /><br />";
        return false;
    }

    // controllo se il file é arrivato a destinazione
    if (!file_exists($file))
    {
        echo "ERRORE : Il file non &egrave; arrivato a destinazione<br /><br />";
        return false;
    }

    // non ho altro da fare
    echo "Il file -- ".$file_name." -- &egrave; stato caricato correttamente.";
    return true;
}
 
Ultima modifica di un moderatore:

marino51

Utente Attivo
28 Feb 2013
3.204
207
63
Lombardia
per pulire la cartella temporanea, in caso di errore, puoi aggiungere "unlink", come sotto riportato
PHP:
    $uploadOk = GestisciUpload($cartella);
    if ( $uploadOk === false ) unlink($_FILES['fileToUpload']['tmp_name']);

    // qui va gestito il comportamento successivo
 

xnotar

Utente Attivo
3 Apr 2012
65
0
6
Ho capito, praticamente gli fai controllare che l'estensione inviata sia effettivamente del MIME definito come tale, però non capisco perché il stl che ha un mime "application/sla" da php non venga riconosciuto e si debba mettere application/octet-stream ?
 

marino51

Utente Attivo
28 Feb 2013
3.204
207
63
Lombardia
ciao
dimenticavo, i controlli possono diventare tre
PHP:
//.....
$type_tmp = $_FILES["fileToUpload"]["type"];
$mime_type_tmp = mime_content_type($_FILES["fileToUpload"]["tmp_name"]);
$est=strtolower(pathinfo($_FILES["fileToUpload"]["name"], PATHINFO_EXTENSION));
//costruire tre array e metterli nell'if
if(in_array($type_tmp, $type) && in_array($mime_type_tmp, $mime) && in_array($est, $tipo)){
    //eccc...  
}
//....
già provato non funziona, può essere imbrogliato
 

marino51

Utente Attivo
28 Feb 2013
3.204
207
63
Lombardia
Ho capito, praticamente gli fai controllare che l'estensione inviata sia effettivamente del MIME definito come tale, però non capisco perché il stl che ha un mime "application/sla" da php non venga riconosciuto e si debba mettere application/octet-stream ?
io credo che il browser possa fare il furbo, restituendo il tipo dall'estensione, se rinomini un jpg in txt, il browser ti dice che tipo = testo ....
mentre php ti restituisce il tipo corretto

suppongo che php non abbia tutte le "definizioni" per interpretare la miriade di possibili file, ma gestisca solo i più comuni

ma incrociando estensione e tipo possiamo limitare i danni
 

marino51

Utente Attivo
28 Feb 2013
3.204
207
63
Lombardia
per favore inserisci la riga in mezzo, usa le altre come riferimento per la posizione
PHP:
    // controllo se è accettabile
    $file_ext = strtolower($file_ext);
    if ( empty($allowed_type[$file_ext]) or $mime_type != $allowed_type[$file_ext] )
 
Discussioni simili
Autore Titolo Forum Risposte Data
S [PHP] Upload stesso file PHP 14
G [PHP] upload file in server: percorso cartella PHP 2
M Upload 4 file php PHP 11
M [PHP] Nome file, upload e rinominare PHP 2
M [PHP] upload di un file esistente overwrite PHP 1
N [PHP] Test per l'upload di file attraverso un bot Telegram PHP 2
C [PHP] Problema upload file (multiplo) PHP 1
S [PHP] Upload file... PHP 6
giancadeejay [PHP] Aggiornare DB tramite UPLOAD file .csv PHP 39
V File upload.php della guida, ma ha un errore PHP 8
francesco7 [Problema] esecuzione script Upload file in php PHP 0
I upload file php / javascript / mysql PHP 0
R upload file php PHP 5
L [PHP e FTP upload] controllo file allegato PHP 6
novello88 PHP upload file PHP 1
B [PHP - MySQL] Upload di un File PHP 6
M UPLOAD File in PhP PHP 3
S Upload File in Php PHP 7
nicocade [help] upload file con php!!! PHP 1
L Upload di un'immagine all'interno di un database usando php PHP 6
S Problemi con modulo upload video php (help!) PHP 0
F [PHP] Informazioni upload PHP 11
D [PHP] Upload intera cartella PHP 2
felino [PHP] Uploadify: upload immagini PHP 0
L [PHP] problema con upload e javascript (upload multiplo) Javascript 2
L [PHP] upload con errore PHP 2
V [PHP] Upload Excel in db PHP 0
jailbait [PHP] Upload immagine e stampa a schermo PHP 0
G PHP upload dati ed immagine PHP 7
F [PHP] Validare form prenotazione appuntamento tattoo con upload image PHP 0
D [PHP] Upload encrypt image PHP 0
P [PHP] Upload multiplo PHP 4
N [PHP] Problema upload immagini wordpress PHP 2
MarcoGrazia [PHP] Upload e successiva visualizzazione immagini in DB PHP 3
S PHP: Aiuto con upload immagini che si auto tuotano PHP 24
C [PHP] Upload immagine in un form con target _blank: non funziona PHP 7
A Upload multiplo di immagini in PHP PHP 3
L [php] upload controllo dimensione immagine PHP 8
F upload foto in php?????? PHP 2
R upload e ridimensionamento immagini in php PHP 0
R upload e ridimensionamento immagini in php PHP 1
L [PHP] Upload immagini e ridimensionamento automatico PHP 9
N [RISOLTO] Upload jpeg e pdf in folder (PHP) PHP 16
K [PHP] multi upload immagine da form PHP 60
L Passare ad uno script PHP i dati di un form incluso l'upload di un'immagine Ajax 0
N problema script php mysql multi upload immagini PHP 31
helpdesk Gif agli eventi di php Upload PHP 6
neo996sps [PHP + MySQL + Server Linux] Upload semi riuscito e query non eseguite PHP 2
Y [PHP/MySQL] Upload PDF PHP 3
O PHP ecommerce > da un sito funzionante > duplicazione riuscita ma non upload immagini PHP 19

Discussioni simili