2011-09-06 27 views
12

Desarrollo un script php para reemplazar uno actual, que tendrá una gran exposición a varios mercados/países. Este script entre otros ofrece una funcionalidad de carga de fotos.Acercamiento de seguridad de carga de imagen PHP

Después de leer mucho sobre el tema, seguí el enfoque que se describe a continuación. Agradecería mucho sus comentarios sobre su seguridad.

  1. La foto se carga en una carpeta privada 777 fuera de la raíz web.
  2. Se realiza una comprobación de las extensiones en la lista blanca (solo permite jpgs, gifs, pngs) se elimina todo lo demás.
  3. Uso de getimagesize para verificar las dimensiones min-max y la validez de la foto.
  4. Comprobación del tipo de letra mimet y la extensión de la extensión de archivo.
  5. Cambio de tamaño de la foto cargada a las dimensiones estándar (utilizando imagecopyresampleado).
  6. Guardando los archivos creados como jpg.
  7. Eliminación del archivo original.
  8. Guarde las fotos con una nueva (nombre no aleatorio) es decir img51244.jpg.
  9. Mueva las nuevas fotos a los subdirectorios variables de una carpeta pública (777 permisos) según un algoritmo no predecible. Es decir, img10000.jpg se almacenará en photos/a/f/0/img10000.jpg, mientras que img10001.jpg se almacenará en photos/0/9/3/img10001.jpg. Esto se hace por otros motivos (uso de subdominios para el servicio de contenido estático o el uso de un CDN).

La secuencia de comandos se ejecutará en un servidor dedicado de Linux.

+0

nada salta a la vista aquí. aparte del permiso 777 en la carpeta, tal como lo entiendo, si tiene 777 permisos, no es privado. pero por lo que puedo decir, esto realmente solo importaría si su servidor se viera comprometido (lo cual no me parece probable a través de este script al menos) – jammypeach

+2

777 no suena seguro. Posible relacionado con http://stackoverflow.com/questions/3644138/secure-user-image-upload-capabilities-in-php – ajreal

+0

Me parece muy bueno, excepto tal vez por permisos muy liberales. Tal vez se pueden limitar de alguna manera? De lo contrario, esto hace todo lo que puedo pensar, incluida la eliminación de datos EXIF ​​ –

Respuesta

3

También debe verificar el tamaño del archivo cargado, ya que getimagesize a veces puede exceder la memoria RAM disponible. También es bueno suponer que su script puede bloquearse en cualquier momento (por ejemplo, cuando la electricidad se apaga), por lo que debe implementar algunos procedimientos de limpieza para eliminar los archivos innecesarios que quedan.

+1

El máximo tamaño de archivo que se puede cargar ya está limitado en php.ini. – Maerlyn

+0

Sí, lo es, pero no significa que sea suficiente para evitar exceder el límite de RAM. –

+0

Si excede el tamaño en php.ini, no obtiene un nombre de archivo en '$ _FILES', por lo que no puede verificar el tamaño. – Maerlyn

-1

Es un enfoque bastante completo, pero no veo ningún mecanismo de prevención de ejecución de código.

Debe asegurarse de que el contenido de la imagen nunca se incluya (con una llamada include o require) o ejecutado a través de eval().

De lo contrario, podría ejecutarse el código php incluido al final del archivo.

También puede intentar detectar el código php dentro del contenido de la imagen (con file_get_contents, y luego una expresión regular buscando "<? Php" por ejemplo) pero no pude encontrar una forma 100% segura de eliminar código sospechoso sin destruir algunas imágenes (válidas)

+0

No veo cómo se ejecutará el código PHP en un archivo JPG a menos que el servidor esté mal configurado? –

+0

No tiene sentido, ya que es obvio que nadie va a llamar a eval o incluir en la imagen. No puedo pensar en ningún escenario en el que alguien alguna vez piense en hacerlo (a menos que empiece a usar PHP). –

+0

El archivo original se elimina tan pronto como se reproducen las fotos. se usa solo con las siguientes funciones de php en ese orden: archivo_cargado_movimiento, tamaño de archivo, getimagesize, imagencreadodejuego, imagecopyresampleado. – Alex

4
  1. Un directorio con chmod 0777 es, por definición, público para otros usuarios conectados a su servidor, no privado. Los permisos correctos serían 700 y serán propiedad de apache (o del usuario al que se ejecute su servidor web). No estoy seguro de por qué no usaría el directorio temporal predeterminado de php aquí, ya que también tiende a estar fuera de la raíz web.
  2. Una lista blanca es una buena idea. Tenga cuidado de tener una implementación correcta. Por ejemplo, la expresión regular /.png/ en realidad coincide con apng.php.
  3. Este paso es una gran idea. Básicamente, verifica la magia del archivo.
  4. No es estrictamente necesario. En los dos pasos anteriores, hemos determinado que la extensión y el formato de archivo son correctos. Si requiere que el cliente especifique un tipo MIME correcto, también debe verificar que el tipo MIME dado y el determinado anteriormente sean equivalentes.

Los pasos 5 a 8 no están relacionados con la seguridad.

Paso 9: supongo que su sitio permite que todos puedan ver cada foto. Si ese no es el caso, debe tener un esquema de URL con URL sustancialmente más largas (por ejemplo, el hash de la imagen).

+1

(-1) 777 no significa público en términos de accesibilidad a través de la web; de esto es de lo que está hablando. Y su ejemplo de expresiones regulares implica que esto es de alguna manera imortance ... y BTW exe es una extensión de Windows ...: -/ – Raffael

+0

@ Raffael1984 Creo que phihag lo sabe. Todavía es público en términos de * accesibilidad para otros usuarios en el mismo servidor web *, que * es * un problema. Pero acepto que el paso 2) es innecesario si lo haces 3) correctamente –

+0

@ Raffael1984 Verdadero. No estoy seguro de por qué ese paso es necesario en absoluto. Actualizado la respuesta. – phihag