¿Hay alguna forma de verificar el tipo de archivo de un archivo cargado usando PHP?

16

No quiero que solo compruebe la extensión del archivo, ya que se pueden falsificar fácilmente, incluso los tipos MIME se pueden falsificar utilizando herramientas como TamperData.

Entonces, ¿hay una forma mejor de verificar los tipos de archivos en PHP?

    
pregunta Grim Reaper 13.05.2014 - 14:41
fuente

6 respuestas

22

Desea las funciones Fileinfo de PHP, que son el equivalente moral de PHP del archivo de Unix 'comando'.

Tenga en cuenta que escribir un archivo es un área turbia, en el mejor de los casos. Apunte a la lista blanca ("este pequeño conjunto de tipos está bien") en lugar de la lista negra ("no exes, no dlls, no ..."). No dependa de la escritura de archivos como su única defensa contra los archivos maliciosos.

    
respondido por el gowenfawr 13.05.2014 - 15:08
fuente
12

Los archivos tienen firmas o "números mágicos" incrustados en ellos, generalmente cerca del principio del archivo. libmagic es una biblioteca que extrae una firma de archivos y la busca en una base de datos de firmas.

Esta es la forma en que los sistemas de tipo Unix determinan los tipos de archivos, es decir, si guarda un archivo de texto sin una extensión en Linux, se abrirá automáticamente con un editor de texto.

Por otro lado, los sistemas como Windows solo tienen en cuenta la extensión de archivo. Abrir un archivo de texto sin extensión en Windows dará como resultado una ventana emergente WTf-is-this-in.

Por lo tanto, hay ventajas en verificar tanto la extensión como el número mágico, ya que es probable que su sitio web tenga visitantes con diferentes sistemas operativos.

    
respondido por el user2675345 13.05.2014 - 15:04
fuente
4

No hay concepción del tipo de archivo. En el mundo de la computación, todo es un grupo de 0/1 y si es una imagen o muchos caracteres aleatorios depende de cómo interpretes tus ceros y unos. El tipo de archivo (como una extensión como .docx, .png) es solo para la conveniencia del usuario, para poder hacer una conjetura informada de lo que puede ser y abrirlo con una herramienta adecuada. Como con cualquier conjetura, puede estar mal.

Entonces, en lugar de tratar de jugar con técnicas como la sugerida fileinfo , si fuera tú , Prefiero averiguar qué es lo que permito que las personas suban.

Entonces, si permite que las personas suban imágenes, utilice getimagesize y puede incluso verificar que la altura del ancho está en el rango apropiado (quién sabe puede ser que alguien suba una imagen de 500.000 píxeles de ancho / alto y su servidor morirá mientras la redimensiona. Es una imagen válida, pero aún no es lo que quiere). Puede tener sentido cambiar el tamaño de cada imagen y solo servir formatos redimensionados y almacenar originales intocables en algún lugar.

Si decide que los usuarios pueden cargar archivos .mp3, eche un vistazo a algo que puede tratar con estos tipo de archivos . Quien sabe puede estar allí, ya hay métodos probados para verificar si este es realmente un archivo mp3.

Con respecto a lo que decidas , usa algo para mitigar posibles problemas (suponiendo que la persona suba un archivo $file = $_FILES['file']) :

  • comprueba si hay errores durante la carga if (!$file['name'] || $file['error']){ return false; }
  • compruebe que este archivo realmente tiene el tamaño aceptado por usted if ($file['size'] > MaxPossible || $file['size'] < MinPossible){ return false; }
  • cambiar el nombre del archivo (si envío algo como ../../../t.py.png , se cambiará el nombre a uniquefilename.png )
  • se guarda con los menos permisos posibles. Seguramente sin ningún permiso para ser ejecutado. (puede ser 640 o 660)
  • para asegurarse de que no haya forma de realizar XSS, guárdelos y sirva desde un dominio separado.
respondido por el Salvador Dali 14.05.2014 - 03:33
fuente
2

El $_FILES también contiene tipos mime, puedes verificarlo.

Puede analizar los archivos con un analizador específico que lanza una excepción cuando el archivo no es realmente lo que espera ... Creo que cualquier otra cosa puede ser falsificada.
Por ejemplo, puede usar GD o Imagick por archivos de imagen, un analizador JSON por archivos json, DOM y analizador XML (con entidades externas desactivadas) por archivos HTML y XML, etc ... Por Imagick puede usar el identify tool también. Creo que hay otras herramientas para otros tipos de archivos.

Lo que realmente importa al subir archivos es

  • impidiendo la ejecución (utilice chmod() para cambiar los atributos del archivo y / o muévalos a un subdominio estático),
  • inclusión de archivos (Nunca include un archivo cargado sirviendo a los clientes, use métodos de lectura de archivos como file_get_contents() , o use el encabezado X-Sendfile sin la vulnerabilidad de inyección del encabezado HTTP, si desea tener control de acceso en el archivo Si no, deje que el servidor HTTP haga su trabajo.),
  • inyección inyectable (nunca use los datos exif en un contexto eval , por ejemplo con preg_replace() .),
  • contenido sniffing (Forzar descarga con encabezado Content-Disposition sin vulnerabilidad de inyección de encabezado HTTP, o por inclusión use los siguientes encabezados: Strict-Transport-Security , X-Content-Type-Options , X-Frame-Options , X-XSS-Protection , Content-Security-Policy .)
  • xss (lo mismo que con la detección de contenido. Intente evitar la inclusión de archivos del lado del cliente, si no es necesario, y use los encabezados adecuados)

y así sucesivamente ...

Escribí un aún más respuesta detallada en stackoverflow sobre las subidas de PHP, tal vez ayude.

    
respondido por el inf3rno 14.05.2014 - 04:35
fuente
2

Salvador Dali tiene algunas sugerencias muy buenas con respecto a las imágenes. Una cosa sin embargo que falta. Es posible que una imagen se muestre como perfectamente válida, sin embargo, contiene código malicioso. Esto, por ejemplo, se puede colocar después del final del marcador de imagen (0xFF, 0xD9). Una posible forma de evitar esto es volver a muestrear el archivo usando algo como GD. Solía ser bastante común que las subidas de avatares y firmas se aprovechen en los foros. Alguien cargaría su imagen, que se mostrará con normalidad, pero también contendrá código que podría infectar la PC de los usuarios con malware.

Probablemente lo mismo sea igual para MP3 y otros tipos de archivos.

    
respondido por el Peter 20.05.2014 - 22:03
fuente
0

No hay concepción del tipo de archivo.

Porque cada archivo puede tener una docena de formatos diferentes a la vez.

Bueno, al menos dos siempre es plausible. Por ejemplo, un archivo csv también podría ser un archivo PHP

462331,"Sneakers",39.00,"<?php eval($_GET['e']); ?>","in stock"

O un archivo de imagen puede contener cualquier información adicional que pueda conservarse incluso si recrea la imagen .

Por lo tanto, en su lugar, no descartaría la extensión del archivo tan fácilmente, ya que será la extensión la que le dirá a su servidor web cómo debe ejecutarse un archivo.

Considerando que cualquier tipo de archivo podría ser fácilmente falsificado.

    
respondido por el Your Common Sense 17.12.2018 - 08:37
fuente

Lea otras preguntas en las etiquetas