una subir parte mostrar modificar insertar imagenes imagen guardar eliminar desde datos cargar actualizar php security upload

subir - mostrar imagen en php desde mysql



Lista de comprobación de seguridad de carga de imágenes PHP (11)

Advertencia XSS

Una observación más importante. No sirva / cargue nada que pueda interpretarse como HTML en el navegador.

Dado que los archivos están en su dominio, el javascript contenido en ese documento HTML tendrá acceso a todas sus cookies, lo que permite algún tipo de ataque XSS.

Escenario de ataque:

  1. El atacante carga un archivo HTML con un código JS que envía todas las cookies a su servidor.

  2. El atacante envía el enlace a sus usuarios por correo, PM o simplemente a través de iframe en su sitio o en cualquier otro.

La solución más segura:

Haga que el contenido subido esté disponible solo en el subdominio o en otro dominio. De esta forma, las cookies no serán accesibles. Este es también uno de los consejos de rendimiento de google:

https://developers.google.com/speed/docs/best-practices/request#ServeFromCookielessDomain

Estoy programando un script para subir imágenes a mi aplicación. ¿Los siguientes pasos de seguridad son suficientes para que la aplicación sea segura desde el lado del script?

  • Desactivar PHP se ejecute dentro de la carpeta de carga con .httaccess.
  • No permita la carga si el nombre del archivo contiene la cadena "php".
  • Permitir solo extensiones: jpg, jpeg, gif y png.
  • Permitir solo el tipo de archivo de imagen.
  • No permitir imágenes con dos tipos de archivos.
  • Cambia el nombre de la imagen.
  • Cargar en un subdirectorio no en el directorio raíz.

Este es mi guion:

$filename=$_FILES[''my_files''][''name'']; $filetype=$_FILES[''my_files''][''type'']; $filename = strtolower($filename); $filetype = strtolower($filetype); //check if contain php and kill it $pos = strpos($filename,''php''); if(!($pos === false)) { die(''error''); } //get the file ext $file_ext = strrchr($filename, ''.''); //check if its allowed or not $whitelist = array(".jpg",".jpeg",".gif",".png"); if (!(in_array($file_ext, $whitelist))) { die(''not allowed extension,please upload images only''); } //check upload type $pos = strpos($filetype,''image''); if($pos === false) { die(''error 1''); } $imageinfo = getimagesize($_FILES[''my_files''][''tmp_name'']); if($imageinfo[''mime''] != ''image/gif'' && $imageinfo[''mime''] != ''image/jpeg''&& $imageinfo[''mime''] != ''image/jpg''&& $imageinfo[''mime''] != ''image/png'') { die(''error 2''); } //check double file type (image with comment) if(substr_count($filetype, ''/'')>1){ die(''error 3'') } // upload to upload direcory $uploaddir = ''upload/''.date("Y-m-d").''/'' ; if (file_exists($uploaddir)) { } else { mkdir( $uploaddir, 0777); } //change the image name $uploadfile = $uploaddir . md5(basename($_FILES[''my_files''][''name''])).$file_ext; if (move_uploaded_file($_FILES[''my_files''][''tmp_name''], $uploadfile)) { echo "<img id=/"upload_id/" src=/"".$uploadfile."/"><br />"; } else { echo "error"; }

Cualquier nuevo consejo es bienvenido :)


Cree un nuevo archivo .htaccess en el directorio de carga y pegue este código:

php_flag engine 0 RemoveHandler .phtml .php .php3 .php4 .php5 .php6 .phps .cgi .exe .pl .asp .aspx .shtml .shtm .fcgi .fpl .jsp .htm .html .wml AddType application/x-httpd-php-source .phtml .php .php3 .php4 .php5 .php6 .phps .cgi .exe .pl .asp .aspx .shtml .shtm .fcgi .fpl .jsp .htm .html .wml

Solo asegúrate de cambiar el nombre de los archivos que cargas + olvídate de verificar tipos, contenidos, etc.



Estoy usando php-upload-script que crea un nuevo número aleatorio de 4 bytes para cada archivo cargado, luego XORs el contenido del archivo con estos 4 bytes (repitiéndolos tantas veces como sea necesario), y finalmente agrega el 4 bytes al archivo antes de guardarlo.

Para descargar, los 4 bytes tienen que cortarse nuevamente del archivo, los contenidos serán XORed con ellos nuevamente y el resultado se enviará al cliente.

De esta manera, puedo estar seguro de que los archivos que guardo en el servidor no serán ejecutables ni tendrán ningún significado potencial para ninguna aplicación. Además, no necesito ninguna base de datos adicional para almacenar nombres de archivo en.

Aquí está el código que estoy usando para esto:

Subir:

<?php $outputfilename = $_POST[''filename'']; $inputfile = $_FILES["myblob"]["tmp_name"]; $tempfilename="temp.tmp"; if( move_uploaded_file($inputfile, $tempfilename) ) { $XORstring = random_bytes(4); $tempfile=fopen($tempfilename, "r"); $outputfile=fopen($outputfilename, "w+"); flock($outputfilename, LOCK_EX); fwrite($outputfilename, $XORbytes1); while ( $buffer = fread($tempfile, 4) ) { $buffer = $buffer ^ $XORstring; fwrite($outputfilename, $buffer); } flock($outputfilename, LOCK_UN); fclose($tempfile); fclose($outputfile); unlink($tempfilename); } exit(0); ?>

Descargar:

<?php $inputfilename = $_POST[''filename'']; $tempfilename = "temp.tmp"; $inputfile=fopen($inputfilename, "r"); $tempfile=fopen($tempfilename, "w+"); flock($tempfile, LOCK_EX); $XORstring = fread($inputfile, 4); while ( $buffer = fread($inputfile, 4) ) { $buffer = $buffer ^ $XORstring; fwrite($tempfile, $buffer); } flock($tempfile, LOCK_UN); fclose($inputfile); fclose($tempfile); readfile($tempfile); unlink($tempfile); exit(0); ?>


La respuesta más sencilla para permitir a los usuarios subir archivos de forma segura en PHP es: siempre guarde los archivos fuera de la raíz de su documento.

Por ejemplo: si la raíz de su documento es /home/example/public_html , guarde los archivos en /home/example/uploaded .

Con sus archivos a salvo de los límites de ser ejecutados directamente por su servidor web, hay algunas maneras en que puede hacerlos accesibles a sus visitantes:

  1. Configure un host virtual separado para servir contenido estático que nunca ejecute scripts PHP, Perl, etc.
  2. Cargue los archivos en otro servidor (por ejemplo, un VPS barato, Amazon S3, etc.).
  3. Guárdelos en el mismo servidor y use una secuencia de comandos PHP para las solicitudes de proxy para garantizar que el archivo solo sea legible, no ejecutable.

Sin embargo, si va con las opciones 1 o 3 de esta lista y tiene una vulnerabilidad de inclusión de archivos local en su aplicación, su formulario de carga de archivos puede seguir siendo un vector de ataque .


Para la prueba de seguridad de los archivos de imagen, puedo pensar en 4 niveles de valores. Ellos serian:

  • Nivel 1: verifique la extensión (el archivo de extensión termina con)
  • Nivel 2: verifique el tipo MIME ($file_info = getimagesize($_FILES[''image_file'']; $file_mime = $file_info[''mime''];)
  • Nivel 3: Lea los primeros 100 bytes y verifique si tienen algún número en el siguiente rango: ASCII 0-8, 12-31 (decimal).
  • Nivel 4: verifique los números mágicos en el encabezado (primeros 10-20 bytes del archivo). Puede encontrar algunos de los bytes del encabezado de archivos desde aquí: http://en.wikipedia.org/wiki/Magic_number_%28programming%29#Examples

Nota: cargar toda la imagen sería lento.


Para un archivo de imagen, también puede cambiar el permiso de archivo después de cambiar el nombre para asegurarse de que nunca se ejecute (rw-r - r--)


Voy a repetir algo que publiqué en una pregunta relacionada.

Puede detectar el tipo de contenido utilizando las funciones de Fileinfo (mime_content_type () en versiones anteriores de PHP).

Un extracto del manual de PHP en la antigua extensión Mimetype, que ahora se reemplaza por Fileinfo:

Las funciones de este módulo intentan adivinar el tipo de contenido y la codificación de un archivo buscando determinadas secuencias de bytes mágicos en posiciones específicas dentro del archivo. Si bien esto no es un enfoque a prueba de balas, la heurística utilizada hace un muy buen trabajo.

getimagesize() también puede hacer un buen trabajo, pero la mayoría de los otros controles que está realizando no tienen sentido. Por ejemplo, por qué string php no está permitido en nombre de archivo. No va a incluir archivos de imagen dentro del script PHP, solo porque su nombre contiene cadena php , ¿verdad?

Cuando se trata de volver a crear imágenes, en la mayoría de los casos mejorará la seguridad ... hasta que la biblioteca que utiliza no sea vulnerable.

Entonces, ¿qué extensión de PHP se adapta mejor para la recreación segura de imágenes? Revisé el sitio web de CVE details . Creo que el trío aplicable son esas extensiones:

  1. GD (6 vulnerabilidades)
  2. ImageMagick (44 vulnerabilidades)
  3. Gmagick (12 vulnerabilidades)

De la comparación, creo que GD se adapta mejor, porque tiene la menor cantidad de problemas de seguridad y son bastante viejos. Tres de ellos son críticos, pero ImagMagick y Gmagick no funcionan mejor ... ImageMagick parece tener muchos fallos (al menos en lo que respecta a la seguridad), así que elijo Gmagick como segunda opción.


Vuelva a procesar la imagen usando GD (o Imagick) y guarde la imagen procesada. Todos los demás son simplemente aburridos y divertidos para los hackers.

Editar: Y como señaló rr, use move_uploaded_file() para cualquier carga.

Edición tardía: por cierto, querría ser muy restrictivo con su carpeta de carga. Esos lugares son uno de los rincones oscuros donde ocurren muchas hazañas. Esto es válido para cualquier tipo de carga y cualquier lenguaje de programación / servidor. Ver https://www.owasp.org/index.php/Unrestricted_File_Upload


si la seguridad es muy importante, use la base de datos para guardar el nombre del archivo y renombrar el nombre del archivo y aquí puede cambiar la extensión del archivo a algo así como .myfile y crear un archivo php para enviar imágenes con encabezados. php puede ser más seguro y puedes usarlo en la etiqueta img como golpe:

<img src="send_img.php?id=555" alt="">

también verifique la extensión del archivo con EXIF ​​antes de cargarlo.


La mejor manera de mantener su sitio web seguro cuando el usuario cargue imágenes es seguir estos pasos:

  • compruebe la extensión de la imagen
  • compruebe el tamaño de la imagen con esta función "getimagesize ()"
  • después de esto puede usar la función "file_get_contents ()"
  • Al final, debes insertar file_Content en tu base de datos, ¡creo que es la mejor manera! ¿Cuál es tu opinión?