¿Cómo puedo determinar la verdadera extensión / tipo de un archivo mediante programación?

StackOverflow https://stackoverflow.com/questions/481743

Pregunta

Estoy trabajando en un script que procesará las cargas de los usuarios en el servidor y, como una capa adicional de seguridad, me gustaría saber:

¿Hay alguna manera de detectar la verdadera extensión / tipo de archivo de un archivo y asegurarse de que no sea otro tipo de archivo enmascarado con una extensión diferente?

¿Hay un sello de byte o algún identificador único para cada tipo / extensión?

Me gustaría poder detectar que alguien no ha aplicado una extensión diferente al archivo que está cargando.

Gracias,

¿Fue útil?

Solución

No realmente, no.

Deberá leer los primeros bytes de cada archivo e interpretarlo como un encabezado para un conjunto finito de tipos de archivo conocidos. La mayoría de los archivos tienen encabezados de archivo distintos, algún tipo de metadatos en los primeros bytes o primeros kilobytes en el caso de MP3.

Su programa tendrá que simplemente intentar analizar el archivo para cada uno de sus tipos de archivo aceptados.

Para mi programa, envío la imagen cargada a imagemagick en un bloque try-catch, y si explota, entonces supongo que era una mala imagen. Esto debería considerarse inseguro, porque estoy cargando datos binarios arbitrarios (proporcionados por el usuario) en un programa externo, que generalmente es un vector de ataque. aquí, confío en imageMagick para que no le haga nada a mi sistema.

Recomiendo escribir sus propios controladores para los tipos de archivo importantes que pretende usar, para evitar cualquier vector de ataque.

Editar: veo en PHP que hay algunas herramientas para hacer esto por usted.

Además, los tipos MIME son lo que el navegador del usuario afirma que es el archivo. Es útil y útil leerlos y actuar sobre ellos en su código, pero no es un método seguro, porque cualquiera que le envíe archivos incorrectos falsificará los encabezados MIME fácilmente. Es una especie de defensa de primera línea para mantener su código que espera que un JPEG vomite en un PNG, pero si alguien incrustó un virus en un .exe y lo llamó JPEG, no hay razón para no haber falsificado el tipo MIME.

Otros consejos

PHP tiene un par de formas de leer el contenido del archivo para determinar su tipo MIME, dependiendo de la versión de PHP que esté usando:

Eche un vistazo a las Funciones de Fileinfo si está ejecutando PHP 5.3 +

$finfo = finfo_open(FILEINFO_MIME); 
$type = finfo_file($finfo, $filepath);
finfo_close($finfo);  

Alternativamente, consulte mime_content_type para versiones anteriores.

$type = mime_content_type($filepath);

Tenga en cuenta que simplemente validar el tipo de archivo no es suficiente si desea ser realmente seguro. Alguien podría, por ejemplo, cargar un archivo JPEG válido que explote una vulnerabilidad en un renderizador común. Para protegerse contra esto, necesitaría un antivirus bien mantenido.

PHP tiene un superglobal $ _ FILES que contiene información como tamaño y tipo de archivo. Parece que el tipo se toma de una especie de encabezado, no una extensión, pero puedo estar equivocado.

Hay un ejemplo de ello en sitio w3schools .

Voy a probar si se puede engañar cuando tenga la oportunidad.

ACTUALIZACIÓN:

Todos los demás probablemente sabían esto, pero $ _FILES puede ser engañado. Pude determinarlo de esta manera:

$arg = escapeshellarg( $_FILES["file"]["tmp_name"] );
system( "file $arg", $type );
echo "Real type:  " . $type;

Básicamente utiliza el comando archivo de Unix. Probablemente hay mejores formas, pero no he usado PHP en mucho tiempo. Por lo general, evito usar comandos del sistema si es posible.

que aún podría ser falsificado. Me aseguraría de que no pueda (o no) ejecutar un archivo cargado en el servidor automáticamente.

También tendría un escáner de virus / spyware , y dejaría que haga el trabajo por usted.

puede usar el siguiente código que le da el tipo MIME si ha cambiado la extensión, entonces también

$finfo = finfo_open(FILEINFO_MIME_TYPE);
echo $mime = finfo_file($finfo, $_FILES['userfile']['tmp_name']);
finfo_close($finfo);

Usuarios de Windows: solo edite php.ini y descomente esta línea:

extension=php_fileinfo.dll

Recuerde reiniciar Apache para que el nuevo php.ini surta efecto.

En * nix, los primeros dos bytes del archivo le indican (vea " número mágico "). En Windows, ... a veces esto será cierto (& Quot; información del encabezado & Quot;). Es, en última instancia, O.S. dependiente.

Los ejecutables en general tienen " firma " en los primeros bytes; Sin embargo, me resulta difícil determinar cuál es realmente el tipo de archivo.

¿Qué tipos de archivos espera? Tal vez podría verificar que se ajusta a lo que espera y rechazar todo lo demás.

Otros ya han mencionado FileInfo, que creo que es la solución correcta, pero agregaré esto en caso de que no pueda usarlo por alguna razón. La mayoría de las distribuciones (all?) * Nix incluyen un comando llamado file que cuando se ejecuta en un archivo generará su tipo. Tiene un interruptor para generar en formato legible por humanos (predeterminado) o el tipo MIME. Puede hacer que su script invoque este programa en el archivo cargado y lea el resultado. Nuevamente, este no es el enfoque preferido. Si está en Windows, esta utilidad está disponible a través de Cygwin.

¿Es suficiente verificar el tipo MIME? ¿Asumo que cambiar la extensión de un archivo no cambia su tipo MIME?

¿El tipo MIME es un indicador lo suficientemente fuerte como para pasar por aquí?

Gracias por todas las respuestas hasta ahora.

  

¿Es suficiente verificar el tipo MIME? ¿Asumo que cambiar la extensión en un archivo no cambia su tipo MIME? ¿Es el tipo MIME un indicador lo suficientemente fuerte como para pasar por aquí?

Realmente depende de cómo se use.

  • Si proporciona cargas y descargas, entonces nada importa ya que no se ejecuta.
  • Si es manejado por el servidor web, entonces dependerá de cómo esté configurado el servidor web, aunque sujeto a la mayoría del resto de estos comentarios.
  • Si se trata de una imagen, se mostrará o no, o será el objetivo de las vulnerabilidades de la biblioteca de imágenes. Pero solo esos.
  • Algo parecido a un archivo pdf puede no afectar a su servidor, sino a la computadora de la persona que accede al archivo.
  • Si se va a pasar a una función como " system () " entonces volvemos al comportamiento del sistema operativo, como si fuera & "; haga doble clic en &"; y la extensión del archivo podría incluso considerarse.
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top