comment
IRC Chat
play_arrow
Este sitio utiliza cookies propias y de terceros. Si continúa navegando consideramos que acepta el uso de cookies. OK Más Información.

FileClass (subir y descargar archivos)

  • 3 Respuestas
  • 1565 Vistas

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado alexander1712

  • *
  • Underc0der
  • Mensajes: 850
  • Actividad:
    0%
  • Reputación -2
    • Ver Perfil
    • El blog del programador
    • Email
« en: Octubre 10, 2013, 01:00:09 am »
Como no es ninguna novedad, y los que siguen mis aportes en esta comunidad tan querida de underc0de saben, estoy centrando todo mi esfuerzo, mientras programo basecode.org en lograr una serie de "componentes" reusables, y que cumplan con dicho criterio, para lo cual estoy programando de manera que cada componente y parte de mi sistema pueda ser separado, y lo pueda usar en otro código fácilmente, de ésta forma me ahorro todo lo que más pueda escribir código, y así no tengo que escribir una y otra vez el mismo código, ya tengo la lista de clases a mi medida para poder usarlas. (supongo que también sabrán que soy muy reticente a la hora de usar código ageno y que para usar algún código si no es de la documentación oficial de php y que de todos modos reviso varias veces antes de incorporarlo, en códigos de otros autores lo paso por varios criterios de calidad antes de tomarlo como ejemplo para crear mi propio código, pasa que como siempre digo, prefiero hacer las cosas yo y conocer los defectos que tienen perfectamente a usar cosas de otros sin conocer dichos defectos, por eso hasta creé mi propio framework xD)
en fin, traigo una clase para manejar archivos, tiene dos modalidades de uso, para subir un archivo al server, y para obligar a descargar un archivo del server (lo que nos permite descargar archivos como .jpg o lo que fuese)...

para descargar archivos tienen que instanciar la clase pasando como parametros al constructor, la ubicacion del archivo que manejará el objeto, y el nombre del mismo, luego llamar a la función download_file pasando como parametro el nombre que verá la persona que esté descargando el archivo (obviamente con extension incluido)

y la segunda manera para subir archivos es crear el objeto sin pasar parámetros al constructor y llamara a la función upload_file (en la interface explica los parámetros).

como siempre solo incluyen la interfaz y ésta incluirá la clase por si sola, además requiere de mi Trait Property que lo pueden descargar de No tienes permisos para ver links. Registrate o Entra con tu cuenta

bueno como me extendí demaciado el código php no entrará en la publicación sin que SMF me lo corte, asique dejo en una respuesta el código del archivo interface y el archivo de la clase principal.

Un Saludo! :)

Desconectado alexander1712

  • *
  • Underc0der
  • Mensajes: 850
  • Actividad:
    0%
  • Reputación -2
    • Ver Perfil
    • El blog del programador
    • Email
« Respuesta #1 en: Octubre 10, 2013, 01:00:53 am »
FileClassInterface.php

Código: PHP
  1. <?php
  2.  
  3. // se requiere Trait Property
  4.  
  5. Interface IFileClass
  6. {
  7.        
  8.         /*
  9.          * @ $location = carpeta donde se guarda el archivo
  10.          * @ $name = nombre del archivo con extensión incluida
  11.          */
  12.         public function __construct($location = null, $name = null);
  13.        
  14.         /*
  15.          * @ $name = nombre que verá el usuario cuando se le descargue el archivo
  16.          */
  17.         public function download_file($name);
  18.        
  19.         /*
  20.          * @ $nombre_campo = nombre del campo file del formulario para cargar archivo
  21.          * @ $carpeta = carpeta donde se subirá el archivo
  22.          * @ $uniqid = agregar o no un id único para que no se repitan los archivos
  23.          * @ $namecrypt = encriptar nombre del archivo para imposibilitar descarga (se encrypta en md5)
  24.          * @ $extension_valida = arreglo con extensiones válidas
  25.          * @ $file_type = MIME/TYPE del archivo
  26.          * @ $kbmax = Máximos kb que se permiten en la subida (dejar en 0 si no se quiere poner limite)
  27.          * @ $dir = cuando se devuelva la ruta del archivo devolverla con la carpeta o sin la carpeta de su ubicación (osea solo el nombre o toda la ruta completa)
  28.          * ésta función devuelve falso si ubo algún error, o la dirección o nombre del archivo (según lo especificado) de lo que se subió.
  29.          */
  30.         public function upload_file($nombre_campo, $carpeta, $uniqid = false, $namecrypt = false, $extension_valida = No tienes permisos para ver links. Registrate o Entra con tu cuenta('rar'), $file_type = null, $kbmax = 0, $dir = true);
  31.        
  32.         // devuelve si un nombre de archivo tiene o no una extensión X.
  33.         public function validate_extension($filename, $extension);
  34.        
  35.         public function get_name();
  36.         public function set_name($value);
  37.        
  38.         public function get_peso();
  39.         public function set_peso($value);
  40.        
  41.         public function get_type();
  42.         public function set_type($value);
  43.        
  44.         public function get_location();
  45.         public function set_location($value);
  46.        
  47.         public function get_error();
  48.         public function set_error($value);
  49.        
  50.         public function get_error_msg();
  51.         public function set_error_msg($value);
  52.        
  53. }
  54.  
  55. include('FileClass.php');

FileClass.php

Código: PHP
  1. <?php
  2.  
  3. Class FileClass implements IFileClass
  4. {
  5.         use Property;
  6.        
  7.         protected $kb = 1024;
  8.         protected $mb = 1024;
  9.         protected $gb = 1024;
  10.         private $name = null;
  11.         private $peso = null;
  12.         private $type = null;
  13.         private $location = null;
  14.        
  15.         private $error = false;
  16.         private $error_msg = null;
  17.        
  18.         public function __construct($location = null, $name = null)
  19.         {
  20.                 try
  21.                 {
  22.                         if(!No tienes permisos para ver links. Registrate o Entra con tu cuenta($location))
  23.                         {
  24.                                 if(No tienes permisos para ver links. Registrate o Entra con tu cuenta($name)) throw new exception('El nombre del fichero es requerido');
  25.                                 if(!No tienes permisos para ver links. Registrate o Entra con tu cuenta($location.$name)) throw new exception('El fichero no existe');
  26.                                 $this->name = $name;
  27.                                 $this->location = $location;
  28.                                 $this->peso = No tienes permisos para ver links. Registrate o Entra con tu cuenta($location.$name);
  29.                         }
  30.                 } catch(Exception $e)
  31.                 {
  32.                         $this->error = true;
  33.                         $this->error_msg = $e->getMessage();   
  34.                 }
  35.         }
  36.        
  37.         public function download_file($name)
  38.         {
  39.                 No tienes permisos para ver links. Registrate o Entra con tu cuenta("Content-type: application/octet-stream");
  40.                 No tienes permisos para ver links. Registrate o Entra con tu cuenta("Content-Disposition: attachment; filename=\"{$name}\"\n");
  41.                 $fp=No tienes permisos para ver links. Registrate o Entra con tu cuenta($this->location.$this->name, "r");
  42.                 No tienes permisos para ver links. Registrate o Entra con tu cuenta($fp);
  43.                 No tienes permisos para ver links. Registrate o Entra con tu cuenta();
  44.         }
  45.        
  46.         public function upload_file($nombre_campo, $carpeta, $uniqid = false, $namecrypt = false, $extension_valida = No tienes permisos para ver links. Registrate o Entra con tu cuenta('rar'), $file_type = null, $kbmax = 0, $dir = true)
  47.         {
  48.                 try
  49.                 {
  50.                         $this->name = $_FILES[$nombre_campo]['name'];
  51.                         $this->size = $_FILES[$nombre_campo]['size'];
  52.                         $this->type = $_FILES[$nombre_campo]['type'];
  53.                         $this->location = $carpeta;
  54.                         if(No tienes permisos para ver links. Registrate o Entra con tu cuenta($_FILES[$nombre_campo])) throw new exception('Archivo no seleccionado');
  55.                         $id = null;
  56.                         if($uniqid) $id = No tienes permisos para ver links. Registrate o Entra con tu cuenta(No tienes permisos para ver links. Registrate o Entra con tu cuenta());
  57.                         $this->name = $id.$this->name;
  58.                         // verificamos si la extensión es válida
  59.                         $valido = false;
  60.                         for($i = 0; $i<No tienes permisos para ver links. Registrate o Entra con tu cuenta($extension_valida); $i++)
  61.                                 if($this->validate_extension($this->name, $extension_valida[$i]))
  62.                                         $valido = true;
  63.                         if(!$valido) throw new exception('El archivo es de una extensión inválida');
  64.                         // verificamos si el tipo de archivo es valido
  65.                         if(!No tienes permisos para ver links. Registrate o Entra con tu cuenta($file_type) && $this->type!=$file_type) throw new exception('El tipo de archivo es inválido');
  66.                         // verificamos si tiene el tamaño correcto
  67.                         if($kbmax>0 && $this->size > $kbmax*$this->kb) throw new exception('El archivo pesa demaciado');
  68.                         // lo encryptamos si es preciso
  69.                         if($namecrypt)
  70.                                 $this->name = 'file_'.No tienes permisos para ver links. Registrate o Entra con tu cuenta($this->name).'.cab';
  71.                         // verificamos que el directorio tenga los permisos
  72.                         //------------ TODO
  73.                         // ahora lo vamos a mover
  74.                         if (!No tienes permisos para ver links. Registrate o Entra con tu cuenta($_FILES[$nombre_campo]['tmp_name'], $this->location.$this->name)) throw new exception('No se puede mover fichero subido a carpeta especificada');
  75.                         // retornamos el directorio donde se guardó
  76.                         if($dir)
  77.                                 return $this->location.$this->name;
  78.                         else
  79.                                 return $this->name;
  80.                 } catch (Exception $e)
  81.                 {
  82.                         $this->error = true;
  83.                         $this->error_msg = $e->getMessage();
  84.                         return false;
  85.                 }
  86.         }
  87.        
  88.         public Function validate_extension($filename, $extension)
  89.         {
  90.                 $ext_init = No tienes permisos para ver links. Registrate o Entra con tu cuenta($filename) - No tienes permisos para ver links. Registrate o Entra con tu cuenta($extension);
  91.                 $last_ext = null;
  92.                 for($i=$ext_init; $i<No tienes permisos para ver links. Registrate o Entra con tu cuenta($filename); $i++)
  93.                         $last_ext.=$filename[$i];
  94.                 if($last_ext == $extension)
  95.                         return true;
  96.                 else
  97.                         return false;
  98.         }
  99.        
  100.         public function get_name() { return $this->name; }
  101.         public function set_name($value) { $this->name = $value; }
  102.        
  103.         public function get_peso() { return $this->peso; }
  104.         public function set_peso($value) { ; }
  105.        
  106.         public function get_type() { return $this->type; }
  107.         public function set_type($value) { ; }
  108.        
  109.         public function get_location() { return $this->location; }
  110.         public function set_location($value) { $this->location = $value; }
  111.        
  112.         public function get_error() { return $this->error; }
  113.         public function set_error($value) { ; }
  114.        
  115.         public function get_error_msg() { return $this->error_msg; }
  116.         public function set_error_msg($value) { ; }
  117.  
  118. }
« Última modificación: Marzo 27, 2014, 05:21:16 pm por Expermicid »

Desconectado WHK

  • *
  • Underc0der
  • Mensajes: 68
  • Actividad:
    0%
  • Reputación 3
  • 吴阿卡
    • Ver Perfil
    • WHK
« Respuesta #2 en: Noviembre 04, 2013, 09:40:27 am »
Hola, eso es vulnerable, recuerda que en php == no es lo mismo que ===,

if($last_ext == $extension)

en este punto si extension es true o 1 entonces la validación se resuelve en true independiente que extensión tengas filtrado ya que en php == resuelve primero tipos integers por defecto y despues strings y esas cosas.

Además tampoco filtra mayusculas o minusculas, tampoco verifica que venga con un punto de la extensión, o sea que te podría subir un archivo test.php%00rar y dependiendo del servidor web debería dejarlo subir (creo que las verisones nuevas de apache ya no se puede).

Te recomiendo que le des una vuelta a este ejemplo:
$extension = pathinfo($archivo, PATHINFO_EXTENSION);

El $file_type da lo mismo porque se puede modificar desde una petición post porque eso lo da el navegador, modificable por cualquier persona con complementos como el tamper data o el modify headers de firefox o usando sockets con netcat.

Y cuidado con la función download_file() porque te permite bajar cualquier archivo incluyendo los no permitidos tales como ../../../../../../../etc/passwd o .htaccess o index.php o ../config.php etc.

Dale una vuelta mas, no está mala la clase pero aun le falta.

Saludos.


Desconectado alexander1712

  • *
  • Underc0der
  • Mensajes: 850
  • Actividad:
    0%
  • Reputación -2
    • Ver Perfil
    • El blog del programador
    • Email
« Respuesta #3 en: Noviembre 04, 2013, 02:16:30 pm »
No tienes permisos para ver links. Registrate o Entra con tu cuenta
Hola, eso es vulnerable, recuerda que en php == no es lo mismo que ===,

if($last_ext == $extension)

en este punto si extension es true o 1 entonces la validación se resuelve en true independiente que extensión tengas filtrado ya que en php == resuelve primero tipos integers por defecto y despues strings y esas cosas.

Además tampoco filtra mayusculas o minusculas, tampoco verifica que venga con un punto de la extensión, o sea que te podría subir un archivo test.php%00rar y dependiendo del servidor web debería dejarlo subir (creo que las verisones nuevas de apache ya no se puede).

Te recomiendo que le des una vuelta a este ejemplo:
$extension = pathinfo($archivo, PATHINFO_EXTENSION);

El $file_type da lo mismo porque se puede modificar desde una petición post porque eso lo da el navegador, modificable por cualquier persona con complementos como el tamper data o el modify headers de firefox o usando sockets con netcat.

Y cuidado con la función download_file() porque te permite bajar cualquier archivo incluyendo los no permitidos tales como ../../../../../../../etc/passwd o .htaccess o index.php o ../config.php etc.

Dale una vuelta mas, no está mala la clase pero aun le falta.

Saludos.

claro, interesante lo que propones, muchisimas gracias, le pegaré las retocadas según la recomendación, como le decía el otro día a antrax, yo se programar razonable, pero no se mucho de seguridad, por eso siempre trato de juntarme con alguien que la tiene clara, dejando eso de lado, es cierto que el === es diferente a == ya que el === agrega una comparación de tipos, no obstante los tipos dinámicos de php son muy impredecibles, por lo que muchas veces da problemas serios con los tipos de datos, por eso trato de usar el === solo cuando realmente es necesario, como en el ejemplo que tu das, es verdaderamente útil, solo quiero aclarar eso porque encontré algunos errores a la hora de hacer comprobaciones de tipo, sobretodo cuando estaba experimentando con NCurses.

Saludos y desde ya muchas gracias por el comentario, realmente es muy útil, si tienes alguna otra sugerencia por favor hazmela saber, no siempre encuentro a personas que me digan en lo que me equivoco o lo que puedo mejorar :)

pd: si tienes alguna sugerencia de algún otro método más eficaz para comprobar la estructura de un archivo además de por su extención sería también de mucha utilidad.
« Última modificación: Noviembre 04, 2013, 02:18:52 pm por Harkonnen »

 

¿Te gustó el post? COMPARTILO!



[PHP] Envio de archivos con POST

Iniciado por ANTRAX

Respuestas: 0
Vistas: 1019
Último mensaje Febrero 24, 2010, 11:46:31 am
por ANTRAX
[Videotutorial] Editor de archivos en PHP

Iniciado por HckDrk

Respuestas: 0
Vistas: 1372
Último mensaje Enero 03, 2013, 04:48:29 pm
por HckDrk
Descargar imagenes externas con PHP y cURL

Iniciado por Xt3mP

Respuestas: 0
Vistas: 4618
Último mensaje Abril 20, 2012, 02:45:22 am
por Xt3mP
Subir Directorios Completos por FTP

Iniciado por s00rk

Respuestas: 7
Vistas: 1692
Último mensaje Junio 02, 2011, 11:32:39 pm
por Xt3mP