Seguridad del sistema de archivos
PHP está sujeto a la seguridad misma de la mayoría de
sistemas de servidores en lo que a permisos sobre archivos y
directorios se refiere_ Esto le permite controlar cuáles
archivos en el sistema de archivos pueden ser leídos_ Debe
tenerse cuidado con aquellos archivos que tengan permisos de lectura
globales, para asegurarse de que su contenido es seguro y no
represente peligro el que pueda ser leído por todos los
usuarios con acceso al sistema de archivos_
Ya que PHP fue diseñado para permitir acceso al nivel de
usuarios al sistema de archivos, es completamente posible escribir un
script PHP que le permita leer archivos del sistema como /etc/passwd,
modificar sus conexiones tipo ethernet, enviar trabajos de
impresión masivos, etc_ Esto tiene algunas implicaciones
obvias, en el sentido en que usted tiene que asegurarse de que los
archivos desde lo que lee y hacia los que escribe datos, sean los
correctos_
Considere el siguiente script, en donde un usuario indica que quisiera
eliminar un archivo ubicado en su directorio personal_ Este caso asume
que se trata de una situación en donde se usa normalmente una
interfaz web que se vale de PHP para la gestión de archivos,
así que el usuario de Apache tiene permitido eliminar archivos
en los directorios personales de los usuarios_
Ejemplo 15_1_ Un chequeo pobre de variables nos lleva a___ <?php
// eliminar un archivo del directorio personal del usuario
$nombre_usuario = $_POST['nombre_enviado_por_el_usuario'];
$directorio = "/home/$nombre_usuario";
$archivo_a_eliminar = "$archivo_de_usuario";
unlink ("$directorio/$archivo_de_usuario");
echo "¡El archivo $archivo_a_eliminar ha sido eliminado!";
?> |
|
Ya que el nombre de usuario es enviado desde un formulario de usuario,
cualquiera puede enviar un nombre de usuario y archivo propiedad de
otra persona, y eliminar archivos_ En este caso, usted querrá
usar otro método de autenticación_ Considere lo que
sucede si las variables enviadas son "__/etc/" y "passwd"_ El
código entonces se ejecutaría efectivamente como:
Ejemplo 15_2_ ___ un ataque al sistema de archivos <?php
// elimina un archivo de cualquier parte del disco duro al que el
// usuario de PHP tiene acceso_ Si PHP tiene acceso de root:
$nombre_usuario = "__/etc/";
$directorio = "/home/__/etc/";
$archivo_a_eliminar = "passwd";
unlink ("/home/__/etc/passwd");
echo "¡El archivo /home/__/etc/passwd ha sido eliminado!";
?> |
|
Hay dos importantes medidas que usted debe tomar para prevenir estas
situaciones_
Aquí hay una versión mejorada del script:
Ejemplo 15_3_ Un chequeo de nombres de archivos más seguro <?php
// elimina un archivo de cualquier parte del disco duro al que el
// usuario de PHP tiene acceso_
$nombre_usuario = $_SERVER['REMOTE_USER']; // uso de un mecanismo de
// autenticacion
$directorio = "/home/$nombre_usuario";
$archivo_a_eliminar = basename("$archivo_de_usuario"); // remover rutas
unlink ($directorio/$archivo_a_eliminar);
$fp = fopen("/home/registros/eliminacion_log","+a"); // registrar el proceso
$cadena_de_registro = "$nombre_usuario $directorio $archivo_a_eliminar";
fputs ($fp, $cadena_de_registro);
fclose($fp);
echo "¡El archivo $archivo_a_eliminar ha sido eliminado!";
?> |
|
Sin embargo, incluso este caso no está libre de
problemas_ Si su sistema de autenticación le ha permitido a
los usuarios la creación de sus propios nombres en el
sistema, y un usuario elige "__/etc/", el sistema se encuenrta
nuevamente expuesto_ Por esta razón, puede que uster
prefiera escribir un chequeo más personalizado:
Ejemplo 15_4_ Chequeo de nombres de archivos aun más seguro <?php
$nombre_usuario = $_SERVER['REMOTE_USER']; // uso de un mecanismo de
// autenticacion
$directorio = "/home/$nombre_usuario";
if (!ereg('^[^_/][^/]*$', $archivo_de_usuario))
die('nombre de archivo inválido'); // finalizar,
// no ejecutar el proceso
if (!ereg('^[^_/][^/]*$', $nombre_usuario))
die('nombre de archivo inválido'); // finalizar,
// no ejecutar el proceso
//etc___
?> |
|
Dependiendo de su sistema operativo, existe una amplia variedad de
archivos sobre los que usted debería estar atento, incluyendo
las entradas de dispositivos (/dev/ o COM1), archivos de
configuración (archivos /etc/ y los archivos _ini), areas
conocidas de almacenamiento de datos (/home/, Mis Documentos),
etc_ Por esta razón, usualmente es más sencillo crear
una política en donde se prohíba toda transacción
excepto por aquellas que usted permita explícitamente_