Seguridad
PHP Manual

Seguridad del Sistema de Archivos

Tabla de contenidos

PHP está sujeto a la seguridad integrada en la mayoría de sistemas de servidores con respecto a los permisos de archivos y directorios. Esto permite controlar qué archivos en el sistema de archivos se pueden leer. Se debe tener cuidado con los archivos que son legibles para garantizar que son seguros para la lectura por todos los usuarios que tienen acceso al sistema de archivos.

Desde que PHP fue diseñado para permitir el acceso a nivel de usuarios para el sistema de archivos, es perfectamente posible escribir un script PHP que le permita leer archivos del sistema como /etc/passwd, modificar sus conexiones de red, enviar trabajos de impresión masiva, etc. Esto tiene algunas implicaciones obvias, es necesario asegurarse que los archivos que se van a leer o escribir son los apropiados.

Considere el siguiente script, donde un usuario indica que quiere borrar un archivo en su directorio home. Esto supone una situación en la que una interfaz web en PHP es usada regularmente para gestionar archivos, por lo que es necesario que el usuario Apache pueda borrar archivos en los directorios home de los usuarios.

Ejemplo #1 Un control pobre puede llevar a ....

<?php
// eliminar un archivo del directorio personal del usuario
$username $_POST['user_submitted_name'];
$userfile $_POST['user_submitted_filename'];
$homedir  "/home/$username";

unlink("$homedir/$userfile");

echo 
"El archivo ha sido eliminado!";
?>
Dado que el nombre de usuario y el nombre del archivo son enviados desde un formulario, estos pueden representar un nombre de archivo y un nombre de usuario que pertenecen a otra persona, incluso se podría borrar el archivo a pesar que se supone que no estaría permitido hacerlo. En este caso, usted desearía usar algún otro tipo de autenticación. Considere lo que podría suceder si las variables enviadas son "../etc/" y "passwd". El código entonces se ejecutaría efectivamente como:

Ejemplo #2 ... Un ataque al sistema de archivos

<?php
// elimina un archivo desde cualquier lugar en el disco duro al que
// el usuario de PHP tiene acceso. Si PHP tiene acceso de root:
$username $_POST['user_submitted_name']; // "../etc"
$userfile $_POST['user_submitted_filename']; // "passwd"
$homedir  "/home/$username"// "/home/../etc"

unlink("$homedir/$userfile"); // "/home/../etc/passwd"

echo "El archivo ha sido eliminado!";
?>
Hay dos medidas importantes que usted debe tomar para prevenir estas cuestiones. Aquí está una versión mejorada del script:

Ejemplo #3 Comprobación más segura del nombre de archivo

<?php
// elimina un archivo del disco duro al que
// el usuario de PHP tiene acceso.
$username $_SERVER['REMOTE_USER']; // usando un mecanismo de autenticación
$userfile basename($_POST['user_submitted_filename']);
$homedir  "/home/$username";

$filepath "$homedir/$userfile";

if (
file_exists($filepath) && unlink($filepath)) {
    
$logstring "Se ha eliminado $filepath\n";
} else {
    
$logstring "No se ha podido eliminar $filepath\n";
}
$fp fopen("/home/logging/filedelete.log""a");
fwrite($fp$logstring);
fclose($fp);

echo 
htmlentities($logstringENT_QUOTES);

?>
Sin embargo, incluso esto no está exento de defectos. Si la autenticación del sistema permite a los usuarios crear sus propios inicios de sesión de usuario, y un usuario eligió la entrada "../etc/", el sistema está expuesto una vez más. Por esta razón, puede que prefiera escribir un chequeo más personalizado:

Ejemplo #4 Comprobación más segura del nombre de archivo

<?php
$username     
$_SERVER['REMOTE_USER']; // usando un mecanismo de autenticación
$userfile     $_POST['user_submitted_filename'];
$homedir      "/home/$username";

$filepath     "$homedir/$userfile";

if (!
ctype_alnum($username) || !preg_match('/^(?:[a-z0-9_-]|\.(?!\.))+$/iD'$userfile)) {
    die(
"nombre de usuario o nombre de archivo incorrecto");
}

//etc...
?>

Dependiendo de sus sistema operativo, hay una gran variedad de archivos a los que debe estar atento, esto incluye las entradas de dispositivos (/dev/ o COM1), archivos de configuracion (archivos /etc/ y archivos .ini), las muy conocidas carpetas de almacenamiento (/home/, Mis documentos), etc. Por esta razón, por lo general es más fácil crear una política en donde se prohíba todo excepto lo que expresamente se permite.


Seguridad
PHP Manual