¿He hecho lo suficiente como para no comprometerme a través de la carga de imágenes?

1

Sé que nunca puedes estar seguro de haber hecho lo suficiente para estar seguro, y también sé que es difícil corregir correctamente la carga de archivos. Antes de hacer esta pregunta, leí algunas de las publicaciones relacionadas aquí como riesgo de carga de imagen por php , ¿qué pasos se deben tomar para validar ... y riesgos de seguridad de la carga .

Pienso que he hecho todo lo que se necesita, pero estaría muy agradecido si alguien pudiera echar un vistazo a lo que tengo y decir si he hecho lo suficiente. Así que estoy ejecutando el último PHP 5.5.9-1+sury.org~saucy+1 en Apache/2.4.7 . Y mi método de carga es el siguiente:

public static function uploadTemp($number, $file){
    //check if the filename exist and upload was without an error
    if (!$file['name'] || $file['error']){
        return false;
    }

    // check if extension is valid
    if (!Helper::validExtension($file['name'])){
        return false;
    }

    // check is the size of file is valid
    if ($file['size'] > (1024 * 1024 * 6) || $file['size'] < 1024 * 10){
        return false;
    }

    // no need to upload images less than 50x50. Also $file['size'] can be spoofed
    $imageSize = getimagesize($file['tmp_name']);
    if ($imageSize === false || $imageSize[0] < 50 || $imageSize[1] < 50){
        return false;
    }

    require_once('SimpleImage.php');
    $image = new SimpleImage();
    $image->load($file['tmp_name']);

    // saving a file to a temporary directory and renaming it.
    $image->save(Image::$tempDir.$number.'.jpg');
    return true;
}

SimpleImage es una herramienta de código abierto para manipular una imagen , dentro de una herramienta que cambié solo una cosa (función guardar para guardar todos los archivos con 644 permisos). Mi $number es una cadena que es una concatenación de un número aleatorio y una marca de tiempo actual, $file = $_FILES['fileToUpload'] y validExtension se ve de la siguiente manera:

public static function validExtension($filename){
    $extensions = array('jpg', 'jpeg', 'png');

    $arr = explode('.', $filename);
    if ( in_array(strtolower(end($arr)), $extensions) ){
        return true;
    } else return false;
}

Mi carpeta temporal tiene permisos 755 .

Entonces, mi pregunta es: ¿me estoy perdiendo algo aquí o cómo puedo mejorarlo?

  • puede restringir permisos adicionales (no necesito hacer nada con las imágenes, excepto para que el cliente las vea. La carpeta se usa solo para cargar imágenes)
  • puede estar cambiando algunos parámetros en php.ini o apache
pregunta Salvador Dali 06.03.2014 - 12:22
fuente

1 respuesta

6
// check if extension is valid

es en gran medida sin sentido. Usted (sabiamente) crea el nombre del sistema de archivos sin ninguna entrada del nombre del archivo original, por lo que la extensión se descarta de todos modos.

Las extensiones de nombre de archivo no son una convención observada globalmente. Incluso en Windows no todos usan las mismas asignaciones de extensión de archivo. Por lo tanto, generalmente no es una buena idea confiar en extensiones particulares.

// no need to upload images less than 50x50

Querrá verificar que las dimensiones de la imagen no sean demasiado grandes. Cargar una imagen enorme (especialmente una muy comprimida) es una buena forma de hacer un servidor DoS.

  

Mi carpeta temporal tiene 755 permisos.

Lo ideal sería que el usuario del servidor web y el propietario del archivo estén en un grupo, por lo que podría otorgarle 750 permisos, lo que le permite escribir archivos sin otorgar los mismos privilegios a otros usuarios del servidor.

  

Cambié solo una cosa (función guardar para guardar todos los archivos con 644 permisos)

Y de forma similar aquí 640, o más probablemente 660 si desea que su usuario propietario pueda escribir en los archivos de los usuarios del servidor web.

  

La carpeta se usa solo para subir imágenes

Asegúrese de hacer cumplir eso en el nivel del servidor, de manera que si logra cargar un archivo .php o .htaccess en ese directorio, no hace nada. No parece que este código lo permita, pero podría haber algún otro defecto que lo haga.

En general, todos los archivos / directorios que se pueden escribir en el usuario del servidor web deben hacerse completamente no ejecutables, ya sea bloqueando el servidor web para hacer solo el servicio de archivos estáticos desde allí, o no sirviendo nada desde allí .

Si está haciendo que el servidor web sirva la imagen fuera del directorio de carga, tiene una variedad de posibles problemas de scripts entre sitios:

  • IE puede rastrear el contenido del archivo para encontrar HTML incrustado en él y tratarlo como una página web (con secuencias de comandos); se puede evitar en versiones más actualizadas usando X-Content-Type-Options header;
  • Java trata el archivo como un applet, ignorando el tipo real; Flash trata el archivo como SWF, ignorando el tipo real; las Políticas del mismo origen de estos complementos no coinciden con las de JavaScript;
  • Flash loadPolicyFile que trata el archivo como un archivo de política de dominio cruzado, ignorando el tipo real y, en versiones anteriores de Flash, contenido mal formado.

Ha mitigado enormemente estos ataques de contenido XSS al cargar y volver a guardar la imagen como JPEG, lo que perturbaría el contenido del archivo, por lo que un atacante no puede incluir el contenido activo tal como está dentro del archivo. .

No es imposible totalmente para un atacante enviar una imagen que ellos saben, cuando PHP la vuelve a guardar, el contenido malicioso elegido aparecerá en algún lugar del archivo. Esto sería bastante difícil, especialmente para un codificador con pérdida como JPEG, y no he escuchado de nadie que lo use en un ataque real, pero es concebible. El formato JPEG no está diseñado específicamente para proporcionar garantías duras sobre la dificultad de crear una entrada para generar una salida elegida (como lo haría un hash criptográfico).

Si desea estar seguro , no hay posibles ataques de carga XSS, la solución habitual es servir sus archivos de datos que no son de confianza de un dominio separado, de modo que la secuencia de comandos de sitios cruzados en ellos no obtener el atacante en su sitio principal.

    
respondido por el bobince 06.03.2014 - 17:43
fuente

Lea otras preguntas en las etiquetas