Gestire con superficialità i file in PHP è sempre rischioso.
Partiamo dall'esempio volutamente errato di uno script che comprime i file CSS:
function minify( $css ) {
$css = preg_replace( '#\s+#', ' ', $css );
$css = preg_replace( '#/\*.*?\*/#s', '', $css );
$css = str_replace( '; ', ';', $css );
$css = str_replace( ': ', ':', $css );
$css = str_replace( ' {', '{', $css );
$css = str_replace( '{ ', '{', $css );
$css = str_replace( ', ', ',', $css );
$css = str_replace( '} ', '}', $css );
$css = str_replace( ';}', '}', $css );
return trim( $css );
}
header( 'Content-type: text/css' );
$file = isset( $_GET[ 'css' ] ) ? $_GET[ 'css' ] : ''; // Molto pericoloso
$content = file_get_contents( $_SERVER['DOCUMENT_ROOT'] . $file ); // Potenziale problema
echo minify( $content ); // Il problema diventa reale
Innanzitutto non sappiamo affatto se la variabile $file
contenga un nome di file CSS valido o meno. Potrebbe ad esempio contenere un nome in un formato diverso da quello CSS o addirittura dello shell code.
Quindi occorre innanzitutto validare il nome del file:
if(preg_match('/^[a-z0-9]+\.css$/', $file)) { // Il formato del nome può variare
// Valido
}
A questo punto non sappiamo ancora se il file richiesto esiste. Occorre verificarlo:
$css_file = $_SERVER['DOCUMENT_ROOT'] . $file;
if(file_exists($css_file)) {
if(is_readable($css_file)) {
// Possiamo usarlo
}
}
Abbiamo verificato che il file esiste e che è accessibile. Potremmo aggiungere un'ulteriore verifica:
$finfo = finfo_open( FILEINFO_MIME_TYPE );
$mimetype = finfo_file( $finfo, $css_file );
finfo_close( $finfo );
if( $mimetype == 'text/css' ) {
// È un file CSS al 100%
}
Qui abbiamo verificato anche il corretto tipo MIME del file richiesto. La ridondanza non sempre è un male.