¿Cuál es el método más seguro para subir un archivo?
-
05-07-2019 - |
Pregunta
La compañía para la que trabajo recientemente se ha visto afectada con muchos ataques de inyección de encabezado y carga de archivos en los sitios que alojamos y, aunque hemos solucionado el problema con respecto a los ataques de inyección de encabezado, todavía tenemos que controlar los ataques de carga.
Estoy tratando de configurar una serie de scripts de carga tipo plug-and-play para usar de forma interna que un diseñador pueda copiar en la estructura de su sitio, modificar algunas variables y tener listo para usar cargar formulario en su sitio. Estamos tratando de limitar nuestra exposición tanto como sea posible (ya hemos cerrado los comandos fopen y shell).
He buscado en el sitio durante la última hora y he encontrado muchas respuestas diferentes relacionadas con métodos específicos que se basan en fuentes externas. ¿Cuál cree que es la mejor solución de solo script que es lo suficientemente específica como para utilizarla como un método confiable de protección? Además, me gustaría mantener el lenguaje limitado a PHP o pseudocódigo si es posible.
Editar: encontré mi respuesta (publicada a continuación) y, aunque hace uso del comando de shell exec (), si bloquea los archivos de script para que no se carguen (lo que hace esta solución muy bien), no tendrás problemas.
Solución
La mejor solución, IMHO, es colocar el directorio que contiene los archivos cargados fuera de " web " entorno y usar un script para hacerlos descargables. De esta manera, incluso si alguien carga un script, no se puede ejecutar llamándolo desde el navegador y no tiene que verificar el tipo de archivo cargado.
Otros consejos
Permitir que solo los usuarios autorizados carguen un archivo. También puedes agregar un captcha para impedir los robots primitivos.
-
En primer lugar, establezca
MAX_FILE_SIZE
en su formulario de carga , y establezca tamaño máximo deini_set('post_max_size', '40M'); //or bigger by multiple files ini_set('upload_max_filesize', '40M'); ini_set('max_file_uploads', 10);
Compruebe el tamaño por los archivos cargados:
if ($fileInput['size'] > $sizeLimit) ; //handle size error here
-
Debería usar
$ _FILES
ymove_uploaded_file ()
para colocar sus archivos cargados en el directorio correcto, o si desea procesarlos, verifique conis_uploaded_file ( )
. (Estas funciones existen para evitar inyecciones de nombre de archivo causadas porregister_globals
.)$uploadStoragePath = '/file_storage'; $fileInput =
Permitir que solo los usuarios autorizados carguen un archivo. También puedes agregar un captcha para impedir los robots primitivos.
-
En primer lugar, establezca
MAX_FILE_SIZE
en su formulario de carga , y establezca tamaño máximo deini_set('post_max_size', '40M'); //or bigger by multiple files ini_set('upload_max_filesize', '40M'); ini_set('max_file_uploads', 10);
Compruebe el tamaño por los archivos cargados:
if ($fileInput['size'] > $sizeLimit) ; //handle size error here
-
Debería usar
$ _FILES
ymove_uploaded_file ()
para colocar sus archivos cargados en el directorio correcto, o si desea procesarlos, verifique conis_uploaded_file ( )
. (Estas funciones existen para evitar inyecciones de nombre de archivo causadas porregister_globals
.)SetHandler none SetHandler default-handler Options -ExecCGI php_flag engine off
Siempre genere un ID aleatorio en lugar de usar el nombre del archivo original .
-
Cree un nuevo subdomain por ejemplo http://static.example.com o al menos un nuevo directorio fuera de
public_html
, para los archivos cargados. Este subdominio o el directorio no deben ejecutar ningún archivo . Establézcalo en la configuración del servidor, o establezca en un < strong>.htaccess
por el directorio.$noExecMode = 0644; chmod($uploadedFile, $noExecMode);
Configúralo con
chmod ()
también.$userContent = '../uploads/malicious.jpg'; include('includes/'.$userContent);
Use
chmod ()
en los archivos recién cargados y configúrelo en el directorio. -
Debes verificar el tipo mime enviado por el hacker. Debería crear una lista blanca de tipos mime permitidos. Permitir solo imágenes si no es necesario ningún otro formato. Cualquier otro formato es una amenaza de seguridad. Imágenes también, pero al menos tenemos herramientas para manejarlas ...
El contenido dañado , por ejemplo: HTML en un archivo de imagen puede causar XSS en los navegadores con sniffing de contenido vulnerabilidad . Cuando el contenido dañado es un código PHP , entonces se puede combinar con una vulnerabilidad eval injection .Strict-Transport-Security: max-age={your-max-age} X-Content-Type-Options: nosniff X-Frame-Options: deny X-XSS-Protection: 1; mode=block Content-Security-Policy: {your-security-policy}
Intente evitar esto, por ejemplo, use un
class autoloader
en lugar de incluir archivos php manualmente ...
Al manejar la inyección de javascript , primero tiene que desactivar xss y detectar contenido en los navegadores . Los problemas de oler el contenido son típicos de los msie más antiguos, creo que los otros navegadores los filtran bastante bien. De todos modos puedes prevenir estos problemas con un montón de encabezados. (No es totalmente compatible con todos los navegadores, pero eso es lo mejor que puede hacer en el lado del cliente).try { $uploadedImage = new Imagick($uploadedFile); $attributes = $uploadedImage->identifyImage(); $format = $image->getImageFormat(); var_dump($attributes, $format); } catch (ImagickException $exception) { //handle damaged or corrupted images }
Puede verificar si un archivo está corrompido con
Imagick identifique
, pero eso no significa una protección completa.X-Download-Options: noopen Content-Disposition: attachment; filename=untrustedfile.html
Si quieres servir a otros tipos mime , siempre debes forzar la descarga por ellos, nunca incluir en páginas web, a menos que realmente sepa lo que está haciendo ...
<*> -
Es posible tener archivos de imagen válidos con un código dentro de ellos, por ejemplo, en los datos de exif . Por lo tanto, debe eliminar exif de las imágenes si su contenido no es importante para usted. Puede hacer eso con
Imagick
oGD
, pero ambos requieren el reenvasado del archivo. Puede encontrar unexiftool
como alternativa. Creo que la forma más sencilla de borrar exif , es cargar imágenes con GD y guárdalos como PNG con la mejor calidad . Por lo tanto, las imágenes no perderán calidad, y la etiqueta exif se eliminará, ya que GD no puede manejarlo. Haz esto con las imágenes subidas como PNG también ...
Si desea extraer los datos de exif , nunca usepreg_replace ()
si elpatrón
oreplacement
proviene de usuario, ya que eso llevará a una inyección inyectable ... Usepreg_replace_callback ()
en lugar deeval regex flag
, si es necesario. (Error común en los códigos de pegado de copia). Los datos de Exif pueden ser un problema si su sitio tiene una vulnerabilidad de eval injection , por ejemplo, si usainclude ($ userInput)
en alguna parte. Nunca use
include ()
,require ()
por los archivos cargados , sírvalos como estáticos o usefile_get_contents ()
oreadfile ()
, o cualquier otra función de lectura de archivos, si desea controlar el acceso.
Rara vez está disponible, pero creo que el mejor enfoque para usar los encabezadosX-Sendfile: {filename}
con los sendfile apache module . Por los encabezados, nunca utilice la entrada del usuario sin validación o desinfección, ya que esto llevará a inyección de encabezado HTTP .
Si no necesita control de acceso (significa: solo los usuarios autorizados pueden ver los archivos cargados), entonces sirva los archivos con su servidor web. Es mucho más rápido ...Use un antivir para verificar los archivos cargados, si tiene uno.
-
Siempre use una protección combinada , no solo un enfoque único. Será más difícil romper tus defensas ...
Siempre genere un ID aleatorio en lugar de usar el nombre del archivo original .
-
Cree un nuevo subdomain por ejemplo http://static.example.com o al menos un nuevo directorio fuera de
<*>public_html
, para los archivos cargados. Este subdominio o el directorio no deben ejecutar ningún archivo . Establézcalo en la configuración del servidor, o establezca en un < strong>.htaccess
por el directorio.Configúralo con
<*>chmod ()
también.Use
chmod ()
en los archivos recién cargados y configúrelo en el directorio. -
Debes verificar el tipo mime enviado por el hacker. Debería crear una lista blanca de tipos mime permitidos. Permitir solo imágenes si no es necesario ningún otro formato. Cualquier otro formato es una amenaza de seguridad. Imágenes también, pero al menos tenemos herramientas para manejarlas ...
<*>
El contenido dañado , por ejemplo: HTML en un archivo de imagen puede causar XSS en los navegadores con sniffing de contenido vulnerabilidad . Cuando el contenido dañado es un código PHP , entonces se puede combinar con una vulnerabilidad eval injection .Intente evitar esto, por ejemplo, use un
<*>class autoloader
en lugar de incluir archivos php manualmente ...
Al manejar la inyección de javascript , primero tiene que desactivar xss y detectar contenido en los navegadores . Los problemas de oler el contenido son típicos de los msie más antiguos, creo que los otros navegadores los filtran bastante bien. De todos modos puedes prevenir estos problemas con un montón de encabezados. (No es totalmente compatible con todos los navegadores, pero eso es lo mejor que puede hacer en el lado del cliente).Puede verificar si un archivo está corrompido con
<*>Imagick identifique
, pero eso no significa una protección completa.Si quieres servir a otros tipos mime , siempre debes forzar la descarga por ellos, nunca incluir en páginas web, a menos que realmente sepa lo que está haciendo ...
<*> -
Es posible tener archivos de imagen válidos con un código dentro de ellos, por ejemplo, en los datos de exif . Por lo tanto, debe eliminar exif de las imágenes si su contenido no es importante para usted. Puede hacer eso con
Imagick
oGD
, pero ambos requieren el reenvasado del archivo. Puede encontrar unexiftool
como alternativa. Creo que la forma más sencilla de borrar exif , es cargar imágenes con GD y guárdalos como PNG con la mejor calidad . Por lo tanto, las imágenes no perderán calidad, y la etiqueta exif se eliminará, ya que GD no puede manejarlo. Haz esto con las imágenes subidas como PNG también ...
Si desea extraer los datos de exif , nunca usepreg_replace ()
si elpatrón
oreplacement
proviene de usuario, ya que eso llevará a una inyección inyectable ... Usepreg_replace_callback ()
en lugar deeval regex flag
, si es necesario. (Error común en los códigos de pegado de copia). Los datos de Exif pueden ser un problema si su sitio tiene una vulnerabilidad de eval injection , por ejemplo, si usainclude ($ userInput)
en alguna parte. Nunca use
include ()
,require ()
por los archivos cargados , sírvalos como estáticos o usefile_get_contents ()
oreadfile ()
, o cualquier otra función de lectura de archivos, si desea controlar el acceso.
Rara vez está disponible, pero creo que el mejor enfoque para usar los encabezadosX-Sendfile: {filename}
con los sendfile apache module . Por los encabezados, nunca utilice la entrada del usuario sin validación o desinfección, ya que esto llevará a inyección de encabezado HTTP .
Si no necesita control de acceso (significa: solo los usuarios autorizados pueden ver los archivos cargados), entonces sirva los archivos con su servidor web. Es mucho más rápido ...Use un antivir para verificar los archivos cargados, si tiene uno.
-
Siempre use una protección combinada , no solo un enfoque único. Será más difícil romper tus defensas ...
Use y configure Hardened-PHP para crear una secuencia de comandos simple usando move_uploaded_file y $ _ FILES superglobal . Cuanto más sencillo sea el script, más seguro será (al menos, tan seguro como la propia versión de PHP)