Riesgos de un formulario de carga de imagen PHP

42

Mi cliente quiere un sitio de fotografía donde los usuarios puedan subir sus fotos en respuesta a las competencias de fotografía. Aunque técnicamente esto no es un problema, quiero saber los riesgos asociados con permitir que cualquier usuario cargue cualquier imagen en mi servidor. Tengo la sensación de que los riesgos son altos ...

Estaba pensando en usar algo como esto enlace

Si permito que usuarios anónimos carguen archivos, ¿cómo puedo asegurar el directorio en el que se cargarán las imágenes (y los archivos potencialmente maliciosos)?

    
pregunta Starkers 19.03.2013 - 12:46
fuente

2 respuestas

75

La mayor preocupación es, obviamente, que los usuarios malintencionados cargarán cosas que no sean imágenes en su servidor. Específicamente, pueden cargar archivos ejecutables o scripts que intentarán engañar a su servidor para que lo ejecuten.

Una forma de protegerse contra esto es asegurarse de que los archivos no sean ejecutables después de que move_uploaded_file en PHP. Esto es tan simple como usar chmod() para establecer 644 permisos.

Tenga en cuenta que un usuario todavía puede cargar scripts PHP u otros scripts y engañar a Apache para que los ejecute dependiendo de su configuración.

Para evitar esto, llame a getimagesize() en los archivos una vez que se hayan cargado y determine qué archivo tipo son. Cambie el nombre de los archivos a un nombre de archivo único y use su propia extensión . De esa manera, si un usuario carga evil.jpg.php , su script lo guardará como 12345.jpg y no será ejecutable. Mejor aún, su script ni siquiera lo tocará, ya que será un JPEG no válido.

Personalmente siempre renombro las imágenes cargadas a la marca de tiempo actual desde time() o un UUID. Esto también ayuda a prevenir contra nombres de archivos muy malvados (como alguien que intenta subir un archivo al que han llamado ../../../../../../../../etc/passwd )

Como protección adicional, puede utilizar lo que a veces se conoce como "Firewall de imagen". Básicamente, esto implica guardar las imágenes cargadas en un directorio que está fuera de la raíz del documento y mostrarlas a través de un script PHP que llama a readfile() para mostrarlos. Esto puede ser un montón de trabajo, pero es la opción más segura.

Una preocupación secundaria es que los usuarios suban demasiados archivos o archivos que son demasiado grandes, que consumen todo el espacio disponible en el disco o que llenan la cuota del usuario de alojamiento. Esto se puede administrar dentro de su software, incluyendo la limitación del tamaño de los archivos individuales, la cantidad de datos que un usuario puede cargar, el tamaño total de todas las cargas, etc. Asegúrese de que el usuario administrador del sitio web tenga una forma de administrar y eliminar estos archivos.

No confíe en ninguno de los datos en $_FILES . Muchos sitios le dicen que verifique el tipo mime del archivo, ya sea desde $_FILES[0]['type'] o verificando la extensión del nombre del archivo. No hagas esto . Todo lo que se encuentre debajo de $_FILES con la excepción de tmp_name puede ser manipulado por un usuario malicioso . Si sabes que solo quieres imágenes, llama a getimagesize , ya que en realidad lee los datos de la imagen y sabrá si el archivo es realmente una imagen.

No confíe en la comprobación de HTTP Referrer para cualquier seguridad. Muchos sitios le recomiendan verificar que el remitente sea su propio sitio para garantizar que el archivo sea legítimo. Esto puede ser fácilmente falsificado.

Para más información, aquí hay algunos buenos artículos:

respondido por el Josh 19.03.2013 - 13:26
fuente
3

Consulte enlace para obtener algunos consejos importantes.

getimagesize () puede ser engañado para que ejecute código PHP.

enlace tiene un comentario de usuario de CertaiN que brinda una mejor alternativa con finfo ( FILEINFO_MIME_TYPE)

    
respondido por el Rodney 10.02.2014 - 19:22
fuente

Lea otras preguntas en las etiquetas