2010-09-04 18 views
10

Estoy implementando una herramienta de carga de imágenes basada en el usuario para mi sitio web. El sistema debería permitir que cualquier usuario cargue archivos JPEG y PNG solamente. Estoy, por supuesto, preocupado por la seguridad y me pregunto cómo las personas más inteligentes que yo sienten sobre las siguientes comprobaciones para permitir las cargas:Capacidades de carga de imágenes seguras en PHP

1) Primero, enumere las extensiones de archivo permitidas en PHP para permitir solo PNG, png, jpg, JPG y JPEG. Recuperar la extensión de archivo del usuario a través de una función como:

return end(explode(".", $filename)); 

Esto debería ayudar a no permitir al usuario la posibilidad de subir algo malicioso como .png.php. Si esto pasa, vaya al paso 2.

2) Ejecute la función php getimageize() en el archivo TMP. A través de algo como:

getimagesize($_FILES['userfile']['tmp_name']); 

Si esto no devuelve falso, proceda.

3) Asegurar un archivo .htaccess se coloca en el directorio de archivos de modo que los archivos dentro de este directorio no puede analizar archivos PHP:

php_admin_value engine Off 

4) Cambiar el nombre de archivo del usuario para algo pre-determinado. ES DECIR.

$filename = 'some_pre_determined_unique_value' . $the_file_extension; 

Esto también ayudará a evitar la inyección SQL como el nombre del archivo será la única variable determinada por el usuario en cualquier consulta utilizados.

Si realizo lo anterior, ¿qué tan vulnerable para el ataque todavía estoy? Antes de aceptar un archivo, debería tener 1) solo permitía jpgs y pngs, 2) Verificó que PHP dice que es una imagen válida, 3) deshabilitó el directorio de las imágenes desde la ejecución de los archivos .php y 4) renombró el archivo de los usuarios a algo único.

Gracias,

+0

Podría utilizar strip_tags en un archivo de imagen para eliminar etiquetas PHP? –

Respuesta

20

En cuanto a los nombres de archivo, nombres aleatorios son definitivamente una buena idea y quitan muchos dolores de cabeza.

Si quiere asegurarse totalmente de que el contenido esté limpio, considere usar GD o ImageMagick para copiar la imagen entrante 1: 1 en una nueva, vacía.

Eso disminuirá ligeramente la calidad de la imagen porque el contenido se comprime dos veces, pero eliminará cualquier información EXIF ​​presente en la imagen original. Los usuarios a menudo ni siquiera saben cuánta información se pone en la sección Metadatos de los archivos JPG. Información de la cámara, posición, horarios, software utilizado ... Es una buena política para los sitios que alojan imágenes eliminar esa información para el usuario.

Además, copiar la imagen probablemente elimine la mayoría de los exploits que usan datos de imagen defectuosos para causar desbordamientos en el software del visor e inyectar código malicioso. Esas imágenes manipuladas probablemente resulten ilegibles para GD.

+6

Gran respuesta. Solo agregaré eso como una defensa adicional, serviré las imágenes de un dominio descartable que no sea el dominio donde estableces las cookies. De esta forma, incluso si la imagen tiene código ejecutable del lado del cliente, la misma política de origen del navegador evitará mucho daño. –

+0

@sri ¡gran idea, no he pensado en eso! –

+0

@SripathiKrishnan cómo configurar un dominio de descarte para imágenes ... cualquier referencia ... para su respuesta – sid

1

Todos los controles parecen buenos, el número 3 en particular. Si el rendimiento no es un problema, o lo estás haciendo en segundo plano, podrías intentar acceder a la imagen usando GD y ver si se trata de una imagen y no de un montón de basura que alguien está tratando de llenar tu servidor.

4

En cuanto a su número 2), no se limite a marcar FALSE. getimagesize también devolverá el tipo de mimo de la imagen.Esto es, con mucho, una forma más segura para comprobar tipo de imagen adecuada de buscar en el tipo MIME de los suministros del cliente:

$info = getimagesize($_FILES['userfile']['tmp_name']); 
if ($info === FALSE) { 
    die("Couldn't read image"); 
} 
if (($info[2] !== IMAGETYPE_PNG) && ($info[2] !== IMAGETYPE_JPEG)) { 
    die("Not a JPEG or PNG"); 
} 
+0

+1 falló una "aunque (muera la línea de comando 3) . – Thomas

+0

woops. Buena captura. Respuesta reparada, y gracias. –

+1

es posible que un archivo sea un gif válido y contenga un código php al mismo tiempo. Así getimagesize() ganó da mucha protección real – Stann