elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Recuerda que debes registrarte en el foro para poder participar (preguntar y responder)


+  Foro de elhacker.net
|-+  Seguridad Informática
| |-+  Hacking
| | |-+  Bugs y Exploits
| | | |-+  Nivel Web (Moderadores: sirdarckcat, WHK)
| | | | |-+  PHP upload security
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: 1 [2] Ir Abajo Respuesta Imprimir
Autor Tema: PHP upload security  (Leído 17,390 veces)
WHK
Moderador Global
***
Desconectado Desconectado

Mensajes: 6.589


Sin conocimiento no hay espíritu


Ver Perfil WWW
Re: PHP upload security
« Respuesta #10 en: 21 Diciembre 2009, 17:29 pm »

bueno el post, creo que solo faltaría quitar permisos de ejecución al directorio dónde se suben los archivos, y error_reporting(0).


Y si por esas casualidades de la vida tienes un sistema de uploads donde tus archivos se guardan en un directorio igual a tu nick o te da la posibilidad de renombrar archivos? que pasaría si alguien le pone de nombre de archivo "../../../../shell.php" ? ya no estaría en el directorio donde no tienes permisos de ejecución y no necesitas un error_reporting a cero para evitar la subida de la shell tal como pasaba con el mod de my_uploads de phpnuke, inluso a veces para hacerles bypass podías subir archivos php con el nombre de x.php. o x.php5 o x.php... y se ejecutaban igual xD o si no le subias un .htaccess para forzar una extensión .ext a ejecutable php
En línea

O_G_T

Desconectado Desconectado

Mensajes: 8


Ver Perfil
Re: PHP upload security
« Respuesta #11 en: 23 Enero 2010, 11:13 am »

hola que tal a todos  ;D
he pasado por este hilos que he encontrado googleando... he leido muchos temas publicados por sh4van3, algunos buenos otros no tantos debo suponer que se trata del mismo user SH4V de undersecurity.net  ya que todos los paper de sh4van3 son una copia exapta de SH4V....

Primero sh4van3 como tu dices Alla Bezroutchko publico esto  en el año 2007 y hoy es obsoleto... exiten muchas cosas que han cambiado desde esa fecha con relacion a php ....  hay muchas funciones antiguas y nuevas de php para el tratamiento de imagenes; como asi tambien existen muchos trucos que pocos revelan, yo no voy a revelar los mios, porque de esta manera mantendre seguras mis aplicaciones.  
Pero voy a mostrar algunas funciones que has descartado en tu codigo y que muchos dejan de lado a la hora de programar un upload de imagenes...

VAMOS AL HECHO:
exif_imagetype ---> determina el tipo de imagen
se puede utilizar en versiones PHP mayores a 4.3.0
ejemplo de uso
Código:
<?php
if (exif_imagetype('imagen_subida.gif') != IMAGETYPE_GIF) {
    echo 'Hey! la imagen no es GIF!!! estas usando el tuto de sh4van3';
}else{
///codigo normal
}
?>

exif_read_data --> en versiones superiores 4.3.0 (recomendado)
lee los encabezados EXIF de un archivo de imagen JPEG o TIFF. De esta manera se puede obtenet los metadatos generados por cámaras digitales utilizadas.

testeo
Código:
<?php
echo "test1.jpg:<br />\n";
$exif = exif_read_data('tests/test1.jpg', 'IFD0');
echo $exif===false ? "No header data found.<br />\n" : "Image contains headers<br />\n";

$exif = exif_read_data('tests/test2.jpg', 0, true);
echo "test2.jpg:<br />\n";
foreach ($exif as $key => $section) {
    foreach ($section as $name => $val) {
        echo "$key.$name: $val<br />\n";
    }
}
?>

exif_thumbnail
Código:
<?php
if (array_key_exists('file', $_REQUEST)) {
    $image = exif_thumbnail($_REQUEST['file'], $width, $height, $type);
} else {
    $image = false;
}
if ($image!==false) {
    header('Content-type: ' .image_type_to_mime_type($type));
    echo $image;
    exit;
} else {
    // no thumbnail available, handle the error here
    echo 'No thumbnail available';
}
?>

LOS SOBRESALIENTES:
imagecopyresampled() copia una porción rectangular de una imagen sobre otra, suavizando los valores de los píxeles mediante interpolación, de forma que al reducir el tamaño de una imagen aún mantiene una buena claridad. img_dst  es la imagen de destino, img_org  es el identificador de la imagen de origen. Si las coordenadas de origen y destino y ancho y alto son diferentes, se encogerá o agrandará el fragmento de imagen según sea necesario. Las coordenadas son relativas a la esquina superior izquierda. Esta función se puede usar para copiar regiones dentro de la misma imagen (si img_dst  es la misma que img_org ) pero si las regiones se superponen, los resultados serán impredecibles.

 imagecopyresized() copia una porción rectangular de una imagen hacia otra imagen. dst_im  es la imagen de destino, src_im  es el identificador de la imagen origen. Si la altura y anchura de las coordenadas de origen y destino difieren se realizará un estrechamiento o un estiramiento apropiado del fragmento de la imagen. Las coordenadas van localizadas sobre la esquina superior izquierda. Esta función se puede usar para copiar regiones dentro de la misma imagen (si dst_im  es igual que src_im ) pero si las regiones se solapan los resultados seran impredecibles.

   Nota: Existe un problema debido a las limitaciones de las imagenes con paleta de colores (255+1 colores). La acción de volver a muestrear o filtrar una imagen, normalmente requiere de más de 255 colores, con los que se usa una aproximación para calcular el nuevo pixel muestreado y su color.
    En las imagenes con paleta de color, se trata de obtener el nuevo color, o el color calculado más próximo en caso de error. Sin embargo, este nuevo color no siempre es el que visualmente es mas semejante. De esta forma, se pueden producir resultados extraños como imagenes vacías.
    Para solventar este problema, se recomienda usar imagenes de color real como imagen destino, que se pueden obtener por ejemplo mediante la función imagecreatetruecolor().

imagecreate Crea una nueva imagen con una paleta de colores

imagecreatefromgif Crear una nueva imagen a partir de un archivo o URL

imagecreatefromjpeg Crea una imagen nueva desde un archivo o URL
devuelve un identificador de imagen que representa a la imagen obtenida a partir del nombre de archivo indicado.
devuelve una cadena vacía si ha fallado. También escribe un mensaje de error, que desafortunadamente se muestra en el navegador como un enlace roto...

imagecreatefrompng() idem anteriores :-)

imagecreatetruecolor Crea una imagen nueva en color real (true color)
devuelve un identificador de imagen representando una imagen en blanco de tamaño anchura  por altura

image_type_to_mime_type envia Mime-Type para image-type utiles para getimagesize, exif_read_data, exif_thumbnail, exif_imagetype.

ahora veamos un ejemplo utilizando todo esto  :rolleyes:

EL SIGUIENTE CODIGO ES PARTE DE UNA APLICACION JQUERY, QUE CONSIDERO BUENA  ;D
Código:
function resizeImage($image,$width,$height,$scale) {
$image_data = getimagesize($image);
$imageType = image_type_to_mime_type($image_data[2]);
$newImageWidth = ceil($width * $scale);
$newImageHeight = ceil($height * $scale);
$newImage = imagecreatetruecolor($newImageWidth,$newImageHeight);
switch($imageType) {
case "image/gif":
$source=imagecreatefromgif($image);
break;
   case "image/pjpeg":
case "image/jpeg":
case "image/jpg":
$source=imagecreatefromjpeg($image);
break;
   case "image/png":
case "image/x-png":
$source=imagecreatefrompng($image);
break;
   }
imagecopyresampled($newImage,$source,0,0,0,0,$newImageWidth,$newImageHeight,$width,$height);

switch($imageType) {
case "image/gif":
  imagegif($newImage,$image);
break;
       case "image/pjpeg":
case "image/jpeg":
case "image/jpg":
  imagejpeg($newImage,$image,90);
break;
case "image/png":
case "image/x-png":
imagepng($newImage,$image);  
break;
    }

chmod($image, 0777);
return $image;
}
function resizeThumbnailImage($thumb_image_name, $image, $width, $height, $start_width, $start_height, $scale){
list($imagewidth, $imageheight, $imageType) = getimagesize($image);
$imageType = image_type_to_mime_type($imageType);

$newImageWidth = ceil($width * $scale);
$newImageHeight = ceil($height * $scale);
$newImage = imagecreatetruecolor($newImageWidth,$newImageHeight);
switch($imageType) {
case "image/gif":
$source=imagecreatefromgif($image);
break;
   case "image/pjpeg":
case "image/jpeg":
case "image/jpg":
$source=imagecreatefromjpeg($image);
break;
   case "image/png":
case "image/x-png":
$source=imagecreatefrompng($image);
break;
   }
imagecopyresampled($newImage,$source,0,0,$start_width,$start_height,$newImageWidth,$newImageHeight,$width,$height);
switch($imageType) {
case "image/gif":
  imagegif($newImage,$thumb_image_name);
break;
       case "image/pjpeg":
case "image/jpeg":
case "image/jpg":
  imagejpeg($newImage,$thumb_image_name,90);
break;
case "image/png":
case "image/x-png":
imagepng($newImage,$thumb_image_name);  
break;
    }
chmod($thumb_image_name, 0777);
return $thumb_image_name;
}
chmod($thumb_image_name, 0755);
return $thumb_image_name;
}

function getHeight($image) {
$size = getimagesize($image);
$height = $size[1];
return $height;
}

function getWidth($image) {
$size = getimagesize($image);
$width = $size[0];
return $width;
}


$large_image_location = $upload_path.$large_image_name;
$thumb_image_location = $upload_path.$thumb_image_name;


if(!is_dir($upload_dir)){
mkdir($upload_dir, 0755);
chmod($upload_dir, 0755);
}



CODIGO DEL ARCHIVO QUE PROCESARA LOS DATOS
Código:
<?php

include'ARCHIVO-CON-EL-CODIGO-ANTERIOR.php';

if ($_POST["upload"]=="Upload") {
//RECIBE DATOS
$userfile_name = $_FILES['image']['name'];
$userfile_tmp = $_FILES['image']['tmp_name'];
$userfile_size = $_FILES['image']['size'];
$userfile_type = $_FILES['image']['type'];
$filename = basename($_FILES['image']['name']);
$file_ext = strtolower(substr($filename, strrpos($filename, '.') + 1));


if((!empty($_FILES["image"])) && ($_FILES['image']['error'] == 0)) {

foreach ($allowed_image_types as $mime_type => $ext) {

if($file_ext==$ext && $userfile_type==$mime_type){
$error = "";
break;
}else{
$error = "Only <strong>".$image_ext."</strong> images accepted for upload<br />";
}
}
//VERIFICA EL TAMAÑO
if ($userfile_size > ($max_file*1048576)) {
$error.= "Images must be under ".$max_file."MB in size";
}

}else{
$error= "Please select an image for upload";
}
//SI TODO ESTA BIEN SUBE LA IMAGEN
if (strlen($error)==0){

if (isset($_FILES['image']['name'])){
/*/VERIFICA LA EXTENSION QUE ES TOMADA POR UNA SESION ESTA PARTE DE LA APLICACION NO HA SIDO PUBLICADA EN ESTE EJEMPLO ESTE ES MERO EJEMPLO DE EMPLEO DE LAS FUNCIONES CITADAS EN ESTE PAPER*/
$large_image_location = $large_image_location.".".$file_ext;
$thumb_image_location = $thumb_image_location.".".$file_ext;

//UNA VEZ CARGADO EL ARCHIVO SE AGREGA LA EXTENSION TOMANDO DESDE SESION
if($_SESSION['user_file_ext']!=$file_ext){
$_SESSION['user_file_ext']="";
$_SESSION['user_file_ext']=".".$file_ext;
}

move_uploaded_file($userfile_tmp, $large_image_location);
chmod($large_image_location, 0777);

$width = getWidth($large_image_location);
$height = getHeight($large_image_location);
//REDUCE LA IMAGEN SI ES MAYOR EN ANCHO QUE EL PERMITIDO
if ($width > $max_width){
$scale = $max_width/$width;
$uploaded = resizeImage($large_image_location,$width,$height,$scale);
}else{
$scale = 1;
$uploaded = resizeImage($large_image_location,$width,$height,$scale);
} ?>

YO CREO QUE ES BUEN CODIGO, PODEIS PROBAR METIENDO TODO EL CODIGO QUE QUERAIS EN LA PELOTITA DEL EJEMPLO DE sh4van3 OS ASEGURO QUE PARA LO UNICO QUE SERVIRA LA PELOTITA ESA, ES  PARA METERSELA EN EL<? echo $mi_nick; ?>   ;D ;D ;D ;D ;D
 SALUDOS!!!
« Última modificación: 23 Enero 2010, 15:00 pm por O_G_T » En línea

WHK
Moderador Global
***
Desconectado Desconectado

Mensajes: 6.589


Sin conocimiento no hay espíritu


Ver Perfil WWW
Re: PHP upload security
« Respuesta #12 en: 23 Enero 2010, 19:29 pm »

Hola, creo que debiste haber puesto tu post en el foro de php y no acá porque lo único que veeo es como utilizar funciones descritas exactamente igual que en php.net

http://cl.php.net/exif
http://cl.php.net/image

Lo digo porque de seguridad no le veo mucho, incluso ese código está mal hecho porque en el caso que hagas multiupload el array de imagenes subidas va a pasar de ser dimensional a multidimensional y tu código va a fallar.
Para solucionar el problema de las transparencias y la cantidad de colores hay alternativas mucho mejores.
Por ejemplo este pequeño código que hize tomando la documentación desde php.net puede hacer lo mismo y mejor:

Código
  1. <?php
  2. $original = 'test.jpg';
  3. $destino = 'test.png'; // La salida siempre será en PNG para no perder calidad
  4.  
  5. $width_d = 100; // ancho de salida en pixeles
  6. $height_d = 100; // alto de salida en pixeles
  7. /* obtengo información del archivo */
  8. list($width_s, $height_s, $type, $attr) = getimagesize($original, $info2);
  9. /* crea el recurso gd para el origen */
  10. if(!$gd_s = imagecreatefromstring(file_get_contents($original)))
  11. die('El archivo no es una imagen.'); // el archivo no es una imagen
  12. /* crea el recurso gd para la salida */
  13. if(!$gd_d = imagecreatetruecolor($width_d, $height_d))
  14. die('El archivo no es una imagen.'); // No maneja GD o escala fuera del limite
  15.  
  16. magealphablending($gd_d, false); // desactivo el procesamiento automatico de alpha
  17. imagesavealpha($gd_d, true); // Alpha original se graba en el archivo destino
  18. /* Redimensiona */
  19. imagecopyresampled($gd_d, $gd_s, 0, 0, 0, 0, $width_d, $height_d, $width_s, $height_s);
  20. unlink($original); // Elimina el archivo original
  21. if(!imagepng($gd_d, $destino)) // Graba la imagen
  22. die('No tiene permisos de escritura sobre el directorio de imagenes.');
  23. imagedestroy($gd_s); // Libera memoria
  24. imagedestroy($gd_d); // Libera memoria
  25. ?>

Ahora, que alguien haya copiado el tuto de alguien mas lo dudo porque es lo mismo que puedes ver en php.net y por algo fueron hechas esas funciones y no solo el o tu lo utilizan sino miles de desarrolladores y no necesariamente lo vieron desde un tutorial.

Si quieres solucionar el problema de la subida de imagenes yo hize una función que puede solucionar eso, talves te sirva. En php.net también sale similar.

Código
  1. function guardar_subidos($directorio_almacenamiento, $extensiones_permitidas = false, $crear_directorio = false, $un_solo_archivo = false){
  2.  
  3.  /* Verifica si hay archivos subidos para ser recibidos */
  4.  if(is_array($_FILES)){
  5.   if(count($_FILES) < 1){
  6.    return false;
  7.   }
  8.  }else{
  9.   return false;
  10.  }
  11.  
  12.  if($un_solo_archivo){
  13.   if(count($_FILES) > 1){
  14.    return array(
  15.     'estado' => 'error',
  16.     'descripcion_error' => 'Solo es permitido subir un solo archivo y se ha detectado mas de uno'
  17.    );
  18.   }
  19.  }
  20.  
  21.  /* Verifica si el directorio de guardado es válido o no */
  22.  if(!is_dir($directorio_almacenamiento)){
  23.   if($crear_directorio){
  24.    if(!mkdir($directorio_almacenamiento, 0755)){
  25.     return array(
  26.      'estado' => 'error',
  27.      'descripcion_error' => 'El directorio a guardar los archivos subidos no existe y fue imposible crear'
  28.     );
  29.    }
  30.   }else{
  31.    return array(
  32.     'estado' => 'error',
  33.     'descripcion_error' => 'El directorio a guardar los archivos subidos no existe'
  34.    );
  35.   }
  36.  }
  37.  
  38.  /* Limpia la ruta del directorio evitando doble slashses y null bytes */
  39.  
  40.  $directorio_almacenamiento = dirname($directorio_almacenamiento.'/archivo.ext').'/';
  41.  
  42.  /* Si no existe el directorio entonces lo creará */
  43.  
  44.  if(!is_dir($directorio_almacenamiento)){
  45.  
  46.   if(!mkdir($directorio_almacenamiento, 0755))
  47.  
  48.    return array(
  49.     'estado' => 'error',
  50.     'descripcion_error' => 'No se pudo crear el nuevo directorio. Verifique los permisos de escritura sobre el directorio raiz'
  51.    );
  52.  
  53.  }
  54.  
  55.  
  56.  /* Procesa cada archivo subido para pasar de un array con uno a dos dimensiones a una sola dimensión */
  57.  foreach($_FILES as $nombre_array => $archivo){
  58.   /* Verifica si se ha subido un solo archivo o varios */
  59.   if(is_array($_FILES[$nombre_array]['name'])){ /* Múltiples archivos */
  60.    /* Procesa cada archivo subido */
  61.    foreach($_FILES[$nombre_array]['name'] as $id => $nombre){
  62.     /* Verifica que no sea un input vacio */
  63.     if($_FILES[$nombre_array]['name'][$id]){
  64.      $subidos[] = array(
  65.       'name' => $_FILES[$nombre_array]['name'][$id],
  66.       'type' => $_FILES[$nombre_array]['type'][$id],
  67.       'tmp_name' => $_FILES[$nombre_array]['tmp_name'][$id],
  68.       'error' => $_FILES[$nombre_array]['error'][$id],
  69.       'size' => $_FILES[$nombre_array]['size'][$id]
  70.      );
  71.     }
  72.    }
  73.   }else{ /* Un solo archivo */
  74.    $subidos[] = $archivo;
  75.   }
  76.  }
  77.  
  78.  /* Verifica si se ha subido algún archivo */
  79.  if(is_array($subidos)){
  80.   /* Procesa cada archivo subido previamente filtrado en un solo array de una dimensión */
  81.   foreach($subidos as $subido){
  82.    if(is_array($extensiones_permitidas)){
  83.     if(archivos::coincide_extension($subido['name'], $extensiones_permitidas)){
  84.      if(move_uploaded_file($subido['tmp_name'], $directorio_almacenamiento.$subido['name'])){
  85.       $resultados[] = array(
  86.        'estado' => 'ok',
  87.        'name' => $subido['name'],
  88.        'type' => $subido['type'],
  89.        'error' => $subido['error'],
  90.        'size' => $subido['size']
  91.       );
  92.      }else{
  93.       $resultados[] = array(
  94.        'estado' => 'error',
  95.        'descripcion_error' => 'El archivo "'.$subido['name'].'" no pudo ser movido. Verifique los permisos de escritura sobre el directorio raiz',
  96.        'name' => $subido['name'],
  97.        'type' => $subido['type'],
  98.        'error' => $subido['error'],
  99.        'size' => $subido['size']
  100.       );
  101.      }
  102.     }else{
  103.      $resultados[] = array(
  104.       'estado' => 'error',
  105.       'descripcion_error' => 'El archivo "'.$subido['name'].'" contiene una extensión no válida',
  106.       'name' => $subido['name'],
  107.       'type' => $subido['type'],
  108.       'error' => $subido['error'],
  109.       'size' => $subido['size']
  110.      );
  111.     }
  112.    }else{
  113.     if(move_uploaded_file($subido['tmp_name'], $directorio_almacenamiento.$subido['name'])){
  114.      $resultados[] = array(
  115.       'estado' => 'ok',
  116.       'name' => $subido['name'],
  117.       'type' => $subido['type'],
  118.       'error' => $subido['error'],
  119.       'size' => $subido['size']
  120.      );
  121.     }else{
  122.      $resultados[] = array(
  123.       'estado' => 'error',
  124.       'descripcion_error' => 'El archivo "'.$subido['name'].'" no pudo ser movido',
  125.       'name' => $subido['name'],
  126.       'type' => $subido['type'],
  127.       'error' => $subido['error'],
  128.       'size' => $subido['size']
  129.      );
  130.     }
  131.    }
  132.   }
  133.  }else{
  134.   return array(
  135.    'estado' => 'error',
  136.    'descripcion_error' => 'No hay archivos para ser subidos'
  137.   );
  138.  }
  139.  
  140.  /* Retorna el resultado */
  141.  return array(
  142.   'estado' => 'ok',
  143.   'datos' => $resultados
  144.  );
  145.  
  146. }
  147.  

Lo usas así:
Código
  1. $data = guardar_subidos('/archivos/imagenes/', array('doc','xls','pdf','ppt'), true); print_r($data);

En ves de hacer criticas destructivas podrias aportar algo que realmente valga la pena, si quieres criticarle algo a alguien mandale un privado mostrando tu molestia pero no vengas al foro lanzando piedras porque alguien le copió a otro que copió funciones desde php.net.
En línea

Páginas: 1 [2] Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
TCM Security
Tutoriales - Documentación
ehn@ 1 2,591 Último mensaje 6 Noviembre 2023, 20:17 pm
por ehn@
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines