Foro de elhacker.net

Programación => PHP => Mensaje iniciado por: gAb1 en 24 Septiembre 2014, 13:16 pm



Título: crear enlaces seguros para las paginas php
Publicado por: gAb1 en 24 Septiembre 2014, 13:16 pm
Hola, me gustaría saber cual es la manera mas segura de crear enlaces seguros para las paginas de mi sitio web.

Acaba de leer un pequeño tutorial donde aparece un codigo con el que se supone que no será facil hackear la web, pero es del año 2006 y tengo dudas por si ya no es tan seguro como lo era antes... Aqui esta el link: Safe Dynamic Includes (http://www.jemjabella.co.uk/2006/safe-dynamic-includes/)

Tambien he visto otra manera: Safe Dynamic Includes (http://wiki.hashphp.org/Safe_Dynamic_Includes), pero tampoco se si hay otras maneras mas seguras para crear los links de una pagina a otra.

Lo normal es las paginas suele ser

Código
  1. <a href="index.php?x=pagename">Link</a>

Pero al parecer cambiando la variable de sesion por otra, el link puede ser de otra manera:

Código
  1. $_GET['x']; -> $_SERVER['QUERY_STRING'];

Código
  1. <a href="index.php?pagename">Link</a>

¿Podriais confirmar que maneras son más seguras?

Gracias!


Título: Re: crear enlaces seguros para las paginas php
Publicado por: engel lex en 24 Septiembre 2014, 19:30 pm
yo uso "tablas de rutas"

es decir, una db que contenga 2 campos, "link" y "ruta", entonces al llamar, busco en la db si algún valor coincide con el recibido, si coincide, se hace un include con la ruta devuelta, eso te sirve incluso al grado que la pagina "producto" puede ser "pagina_de_fondo.php"


Título: Re: crear enlaces seguros para las paginas php
Publicado por: MinusFour en 24 Septiembre 2014, 19:45 pm
¿Enlaces seguros? Las rutas son tan seguras como el código que ejecuta esa ruta en especifico. Es importante 'limpiar' todo input humano o te arriegas a un XSS, RFI o algo peor.


Título: Re: crear enlaces seguros para las paginas php
Publicado por: WHK en 24 Septiembre 2014, 20:07 pm
Es facil... solo debes hacer un array con todas las posibles rutas y luego hacer la comparación con tu parámetro get, si existe la incluyes y si no existe das un 404, de esa manera te aseguras que solamente las rutas reales van a ser solicitadas y nada de cosas extrañas con rutas extrañas.

Por ejemplo:

Código
  1. <?php
  2.  
  3. if(in_array('includes/'.(string)$_GET['sección'].'.php', glob('includes/*.php')))
  4. include('includes/'.(string)$_GET['sección'].'.php');
  5. else
  6. include('includes/404.php');
  7.  

El cast (string) es para que no te de una excepción si te pasan arrays como parámetros.

También puedes aceptar directorios como lo hace wordpress cuando puedes poner un plugin como plugin.php o una carpeta llamada plugin y un index:

Código
  1. <?php
  2.  
  3. /* Es archivo */
  4. if(in_array('includes/'.$_GET['sección'].'.php', glob('includes/*.php')))
  5. include('includes/'.$_GET['sección'].'.php');
  6.  
  7. /* Es directorio */
  8. elseif(in_array('includes/'.$_GET['sección'].'/index.php', glob('includes/*/index.php')))
  9. include('includes/'.$_GET['sección'].'/index.php');
  10.  
  11. /* No existe */
  12. else
  13. include('includes/404.php');
  14.  

Ahora, si usas file_exists() o is_dir() tendrás que tener cuidado con los agujeros de tipo LFI o RFI, usar esas fuinciones para incluir archivos es muy mala práctica.

Según el blog de donde das en enlace ( http://www.jemjabella.co.uk/2006/safe-dynamic-includes/ ) dice que se debe hacer así:

Código
  1. if (strpos($_GET['x'], "/")) {
  2.      $dir = substr(str_replace('..', '', $_GET['x']), 0, strpos($_GET['x'], "/")) . "/";

Es una malisima práctica, muchos sistemas han sido programados de esa manera y estan llenos de agujeros de seguridad como unos mods y plugins para phpnuke, joomla y wordpress, por ejemplo esto sería vulnerable en base a ese código:

index.php?x=.htpasswd

a demás strpos() solo te indica la primera coincidencia, o sea que yo podría escribir algo//algo y bypasear el filtro, insertar carácteres nulos para cortar el include con un %00, etc etc.


Título: Re: crear enlaces seguros para las paginas php
Publicado por: gAb1 en 24 Septiembre 2014, 21:15 pm
Gracias por las respuestas.

Eso de la tabla de rutas que comenta engel lex es interesante, es algo parecido a lo que comenta WHK, las "whitelist".

Pero en el ejemplo que has puesto, ¿asi tal cual sería seguro? sin hacer un preg_replace o str_replace? Y lo que dice MinusFour, lo de limpiar los input, tiene algo que ver tambien con sanitizar?

Me gustaría algo para no tener que mostrar la ruta, simplemente un nombre, poniendo la ruta en el script.

Por ejemplo si quiero llamar al archivo: register.php dentro de 'views/user/'

Y el link quedase: index.php?register ¿O esto no es seguro?

Pero no se si seria un problema para mostrar el contenido, lo que quiero hacer tambien y no se si hay otra manera mejor, es tener un layout con header (header+menu) y footer, y en medio haciendo un echo content(); para cargar el contenido de los views y no tener que cambiar nada del layout en todas las paginas de contenido. El index.php cargaría el layout y el layout cargaria los views.

¿Hay algún problema para hacer eso? Supongo que hara falta crear una funcion para cargar el contenido.

Gracias!


Título: Re: crear enlaces seguros para las paginas php
Publicado por: WHK en 24 Septiembre 2014, 22:24 pm
Pero en el ejemplo que has puesto, ¿asi tal cual sería seguro? sin hacer un preg_replace o str_replace? Y lo que dice MinusFour, lo de limpiar los input, tiene algo que ver tambien con sanitizar?

Así es, es un método muy seguro, no te tienes que estar preocupando de tener que modificar tu código o base de datos cada ves que agregas secciones nuevas porque se verifican automáticamente en cada carga.

no necesitas un replace ni un limpiado de rutas ni nada de eso, es como si estuvieras intentando tapar el sol con un dedo, son técnicas que no siempre funcionan y son por decirlo muy absurdas, generalmente se ven en códigos hechos por menores de edad o personas que recién están aprendiendo a programar. Es similar a lo que antiguamente muchos hacían... ponerle safe mode en on para supuestamente proteger los servidores, muchos lo hacían pero al final no servía de mucho.

Lo de limpiar inputs es una pesima práctica, es como tratar de enumerar todas las posibles maneras que existen de como robar una casa, siempre habrá alguien que encuentre una manera nueva de entrar, en ves de eso haz una casa normal con seguros en las puertas y listo.

Por lo general debido a personas que piensan que limpiando inputs van a solucionar los problemas de seguridad es porque hoy en día hay tantos sitios expuestos a vulnerabilidades. Puede servir para intentar prevenir algunos tipos de ataques basicos pero jamas para detener todo lo que existe, en este caso limpiar inputs para prevenir el lfi o el rfi es un tema demasiado extenso y complejo si no quieres usar listas blancas, ya existen muchos sistemas que llevan años intentando solucionar este problema en base a filtros tales como phpnuke y algunos sistemas en .NET, por esocorta por lo sano y haz una lista blanca, es rápido y ultra seguro, todos los inputs que no contengan una url real serán rechazadas aunque sean rutas validas, es lo mas sano.


Título: Re: crear enlaces seguros para las paginas php
Publicado por: MinusFour en 24 Septiembre 2014, 23:01 pm
Te estas llendo por las ramas WHK.

Filtrar texto si puede ser una mala práctica, pero cuando yo dije 'limpiar' (y lo puse entre comillas por una buena razón, porque no es exactamente limpiar) no me estaba refiriendo a filtrar el texto (que esto bien puede ser una mala forma de 'limpiar' input). Al decir yo limpiar, me estoy refiriendo a someter el input a un proceso que no permita una anomalía en la ejecución del código. Y 'limpiar' si que es una buena práctica.

Tampoco tienes que generalizar, filtrar texto se sigue haciendo. No como medida de seguridad pero si se sigue usando para los inputs.


Título: Re: crear enlaces seguros para las paginas php
Publicado por: gAb1 en 25 Septiembre 2014, 00:14 am
Gracias, acaba de armar algo y parece funcionar correcto, ¿veis algo mal? ¿es seguro?

index.php
Código
  1. <?php
  2.  
  3. include_once 'themes/default/views/layouts/main.php';
  4.  
  5. $whitelist_home = array("home");
  6. $whitelist_site = array("site/login", "site/logout", "site/contact", "site/about");
  7. $whitelist_user = array("user/register", "user/referral", "user/friend", "user/register_success");
  8.  
  9. if(in_array($_SERVER['QUERY_STRING'], $whitelist_home)) {
  10. if(in_array('views/'.(string)$_SERVER['QUERY_STRING'].'.php', glob('views/*.php'))) {
  11. $home = include('views/'.(string)$_SERVER['QUERY_STRING'].'.php');
  12. } else include('views/404.php');
  13. } elseif(in_array($_SERVER['QUERY_STRING'], $whitelist_site)) {
  14. if(in_array('views/'.(string)$_SERVER['QUERY_STRING'].'.php', glob('views/site/*.php'))) {
  15. $content = include('views/'.(string)$_SERVER['QUERY_STRING'].'.php');
  16. } else include('views/404.php');
  17. } elseif(in_array($_SERVER['QUERY_STRING'], $whitelist_user)) {
  18. if(in_array('views/'.(string)$_SERVER['QUERY_STRING'].'.php', glob('views/user/*.php'))) {
  19. $content = include('views/'.(string)$_SERVER['QUERY_STRING'].'.php');
  20. } else include('views/404.php');
  21. }
  22.  
  23. if(!$_SERVER['QUERY_STRING']) {
  24. echo $home = include('views/home.php'); // Esta es la pagina que se muestra por defecto
  25. }
  26.  
  27. if($_SERVER['QUERY_STRING'] == "home") {
  28. echo $home;
  29. }elseif(in_array($_SERVER['QUERY_STRING'], $whitelist_site)) {
  30. echo $content;
  31. }elseif(in_array($_SERVER['QUERY_STRING'], $whitelist_user)) {
  32. echo $content;
  33.  
  34. ?>

¿Hay algún problema si utilizo ese include_once (lo que uso actualmente para incluir paginas como functions.php) sin ningún if ni nada para mostrar una pagina (que es la base de la web) en el index.php?

Por alguna misteriosa razón justo despues del texto de home.php se añade un 1 sin espacio... ¿Que esta imprimiendo ese 1?

Aparte de que ese script de echos hay que mejorarlo, tiene que ir en el archivo main.php y cuando los he puesto han empezado los errores de variable no definida. Todo son problemas :)

Gracias!


Título: Re: crear enlaces seguros para las paginas php
Publicado por: MinusFour en 25 Septiembre 2014, 05:19 am
Include devuelve 1 si la la inclusión es exitosa, si le haces echo a un include exitosa, este imprime 1. A menos que dentro de tus includes tengas un return, en ese caso el echo toma el valor del return.

El código de WHK está bien para validar todos los archivos de las carpetas. Si vas a trabajar con solo algunos archivos creo que es mejor si tienes una lista para tus includes.

e.g.

Código
  1. <?php
  2.  
  3. $views = 'views/';
  4. $site = $views . 'site/';
  5. $user = $views . 'user/';
  6.  
  7. $includes = array(
  8. 'home' => $views . 'home.php',
  9. 'site/login' => $site . 'login.php',
  10. 'site/logout' => $site . 'logout.php',
  11. 'site/contact' => $site . 'contact.php',
  12. 'site/about' => $site . 'about.php',
  13. 'user/register' => $user . 'register.php',
  14. 'user/referral' => $user . 'referral.php',
  15. 'user/friend' => $user. 'friend.php',
  16. 'user/register_success' => $user . 'register_success.php'
  17. );
  18.  
  19. if(array_key_exists($_SERVER['QUERY_STRING'], $includes)){
  20. include($includes[$_SERVER['QUERY_STRING']]);
  21. }
  22. ?>


Título: Re: crear enlaces seguros para las paginas php
Publicado por: gAb1 en 25 Septiembre 2014, 12:47 pm
Necesito saber como darle un valor por defecto a la variable server, si lo hago asi no lee ningun input y siempre se muestra home...
index.php
Código
  1. <?php
  2.  
  3. include_once 'themes/default/views/layouts/main.php';
  4.  
  5. $views = 'views/';
  6. $site = $views . 'site/';
  7. $user = $views . 'user/';
  8.  
  9. $_SERVER['QUERY_STRING'] = 'home'; // Alguna otra manera?
  10.  
  11. $includes = array(
  12. 'home' => $views . 'home.php',
  13. 'site/login' => $site . 'login.php',
  14. 'site/logout' => $site . 'logout.php',
  15. 'site/contact' => $site . 'contact.php',
  16. 'site/about' => $site . 'about.php.php',
  17. 'user/register' => $user . 'register.php',
  18. 'user/referral' => $user . 'referral.php',
  19. 'user/friend' => $user. 'friend.php',
  20. 'user/register_success' => $user . 'register_success.php'
  21. );
  22.  
  23. if(array_key_exists($_SERVER['QUERY_STRING'], $includes)) {
  24. $content = include($includes[$_SERVER['QUERY_STRING']]);
  25. return true;
  26. } else include('views/404.php');
  27.  
  28. // Esto va en themes/default/views/layouts/main.php
  29. /*
  30. if(array_key_exists($_SERVER['QUERY_STRING'], $includes)) {
  31. echo $content;
  32. }else print_r(error_get_last());
  33. */
  34. ?>

Ahora mismo, sin ningun echo $content se muestra igualmente el include, ¿por que?
¿Como hago para que no se muestre ningún include si no hay un echo?

Gracias.

Edito: Y a todo esto... si necesito hacer inputs en esas paginas, por ejemplo, antes era: login.php?error=1 y ahora como seria? porque ?site/login&error=1 no funciona


Título: Re: crear enlaces seguros para las paginas php
Publicado por: MinusFour en 25 Septiembre 2014, 17:22 pm
Si hay funciones que impriman dentro de tus includes pues entonces esas funciones se van a ejecutar, porque así funcionan los includes().

Código
  1. $content = include($file);

Se ejecuta $file y $content equivale 1.

Ahora si $file tiene:

Código
  1. $html = '<HTML></HTML>';
  2. return $html;

$content ahora tiene <HTML></HTML>.

En cuanto a porque tus rutas no funcionan, es porque estás usando $_SERVER['QUERY_STRING']...

Si tienes:
Citar
index.php?site/login&error=1

Código
  1. $_SERVER['QUERY_STRING'];
  2. //site/login&error=1 != site/login

Y no hace el include en site/login porque no hace match... $_SERVER['QUERY_STRING'] != site/login.

Puedes hacer:

Código
  1. preg_match('/^([\w\/]+)=?(\w+)?&?/', $_SERVER['QUERY_STRING'], $matches);
  2.  
  3. if(array_key_exists($matches[0], $includes)){

Debería hacer un match de la primera palabra en QUERY_STRING. Lo mejor sería manejar las variables GET por llave/valor.

Por ejemplo una url como:

Citar
index.php?do=home

Y en lugar de manejar $_SERVER['QUERY_STRING'] manejar $_GET['do'].

Yo digo que sería mejor tener una URL como:

Código:
http://sitio.com/site/login

En lugar de:

Código:
http://sitio.com/archivo.php?site/login

o

Código:
http://sitio.com/archivo.php?do=site/login

Y para eso puedes implementar un ruteador mejor y tener mas control sobre las urls, aunque tambien una simple regla de mod_rewrite basta.


Título: Re: crear enlaces seguros para las paginas php
Publicado por: gAb1 en 25 Septiembre 2014, 19:37 pm
Citar
Yo digo que sería mejor tener una URL como:

Código:
http://sitio.com/site/login

Esa era la idea en un principio, ahora mismo lo mas cercano a eso que tengo es:

Código:
www.sitio.com/?site/login

Y me gustaría poder hacer eso que comentas... ¿Podrias decirme como podria hacerlo con el mod_rewrite? Ya tengo un .htaccess preparado :)

Pero volviendo al otro problema, es posible hacer que el codigo actual solo lea hasta & y apartir se interprete como otra variable? Para poder hacer que funcione ?site/login&error=1

Gracias!


Título: Re: crear enlaces seguros para las paginas php
Publicado por: WHK en 25 Septiembre 2014, 19:46 pm
Has considerado usar codeigniter?, o sea, si tu duda era solamente hacer un include seguro ya sabes, la lista blanca funciona de lujo pero si vas a hacer un sistema completo en base a ese tipo de inclusiones y códigos redundantes mejor usa uno estandarizado como codeigniter el cual lleva muchos años en el mismo tema, no necesitas reinventar la rueda, puedes tomarlo y ver el código fuente para saber como lo hacen y reutilizar el mismo código.

Si quieres te puedo mostrar un trozo de código de mi framework que hice hace muchos años el cual funciona con includes muy similar al tuyo pero es un poco mas flexible, por ejemplo puedes llamar a
/modulo/submodulo/accion.html?parametros=
y se incluye el archivo correspondiente a cada módulo y submódulo, es mas, soporta multiples niveles, puedes llamar a 5 submodulos si quieres una dentro de otra carpeta y todo en base a una lista blanca para prevenir problemas de seguridad, dale un vistazo para que saques algunas ideas:

Código
  1. <?php
  2. /* CORE - FDC 4.5 - yan.uniko.102@gmail.com, 2009 */
  3. /* Verifica que el archivo no se visualize de forma directa */
  4. if($_SERVER['SCRIPT_FILENAME'] == __file__) exit;
  5.  
  6. $sistema = new sistema();
  7.  
  8. class sistema{
  9. var $navegador = null;
  10. var $modulosSeleccionables = null;
  11. var $contenidoHtml = '';
  12.  
  13. function __construct(){
  14. /* Carga las configuraciones iniciales */
  15. include(dirname(__file__).'/configuraciones.php');
  16. $this->conf = new configuraciones();
  17.  
  18. /* Verifica coherencias en las configuraciones */
  19. if(
  20. isset($this->conf->perfilamiento['habilitado']) and
  21. $this->conf->perfilamiento['habilitado']
  22. ){
  23.  
  24. /* La clase de usuario no funciona sin una base de datos activa */
  25. if(
  26. (!isset($this->conf->mysql['autoCargar'])) or
  27. (!$this->conf->mysql['autoCargar'])
  28. )
  29. return die('
  30. Imposible iniciar el sistema de perfilamiento sin iniciar
  31. una conecci&oacute;n por defecto a la base de datos.
  32. ');
  33. }
  34.  
  35. /* Previene el robo de la cookie de sesión vía XSS */
  36. $cookieSesion = session_get_cookie_params();
  37. session_set_cookie_params($cookieSesion['lifetime'], $cookieSesion['path'], $cookieSesion['domain'], $cookieSesion['secure'], true);
  38. unset($cookieSesion);
  39.  
  40. $this->cargarLibreria('error');
  41. $this->cargarLibreria('str');
  42. $this->cargarLibreria('cabeceras');
  43. $this->cargarLibreria('logs');
  44. $this->cargarLibreria('ids');
  45. $this->cargarLibreria('driver_obj');
  46.  
  47. $this->cabeceras->establecerTipo('text/html');
  48.  
  49. /* Carga la conexión MySQL por defecto */
  50. if(
  51. isset($this->conf->mysql['autoCargar']) and
  52. ($this->conf->mysql['autoCargar'])
  53. ){
  54. $this->cargarLibreria('mysql');
  55. if(!$this->mysql->conectar(
  56. $this->conf->mysql['host'],
  57. $this->conf->mysql['usuario']['nombre'],
  58. $this->conf->mysql['usuario']['clave'],
  59. $this->conf->mysql['baseDeDatos'],
  60. $this->conf->mysql['codificacion'],
  61. $this->conf->desfaceGMT['mysql']
  62. ))
  63. return die($this->mysql->error->ultimo('msg'));
  64. }
  65.  
  66. /* Realiza la autocarga de la sesión de usuario */
  67. if($this->conf->perfilamiento['habilitado']){
  68.  
  69. /* Carga la librería necesaria */
  70. $this->cargarLibreria('usuario');
  71.  
  72. /* Carga la sesión de usuario por defecto via sesión de cookie */
  73. $this->usuario->perfilarViaCookie();
  74.  
  75. /* Reinicia cualquier error de carga fallida */
  76. $this->usuario->error->reiniciar();
  77.  
  78. /* Guarda sesiones temporales solo para usuarios logueados para prevenir una
  79. sobrecarga durante un ataque de DDOS o ataque distribuido */
  80. if($this->usuario->perfilado)
  81. }
  82.  
  83. $this->detectaAgenteDeUsuario();
  84.  
  85. /* Carga las autocargas antes de cargar cualquier otra cosa (librerias
  86. adicionales, módulos, etc) */
  87. $this->establecerAutocargas('pre');
  88.  
  89. /* Verifica la integridad del contexto actual en tema de
  90. * seguridad e intrusión no concentida */
  91. $this->ids->iniciar();
  92.  
  93. $this->contenidoHtml = array(
  94. 'cabecera' => '',
  95. 'modulo' => array()
  96. );
  97.  
  98. /* Obtiene las configuraciones del archivo de configuraciones del template
  99. antes de llamar a los módulos */
  100. if($this->conf->template['habilitado']){
  101.  
  102. /* Existe el template? */
  103. if(!file_exists($this->conf->rutas['template']['local'].'index.php'))
  104. return die('El Template seleccionado no existe.');
  105.  
  106. /* El archivo de configuraciones existe? */
  107. if(!file_exists($this->conf->rutas['template']['local'].'config.php'))
  108. return die('La configuración del Template no existe.');
  109.  
  110. /* Obtiene las configuraciones del template */
  111. include($this->conf->rutas['template']['local'].'config.php');
  112. }
  113.  
  114. $this->cargaModulos();
  115.  
  116. $this->establecerAutocargas('pos');
  117.  
  118. /* Muestra el contenido final entre el módulo y el template */
  119.  
  120. /* Muestra la carga de todos los módulos en orden coorelativo */
  121. $this->contenidoHtml['modulo'] = implode('', $this->contenidoHtml['modulo']);
  122.  
  123. if($this->conf->template['habilitado'])
  124. include($this->conf->rutas['template']['local'].'index.php');
  125. else
  126. echo $this->contenidoHtml['modulo'];
  127.  
  128. /* Cierra la conexión MySQL */
  129. if(is_object($this->mysql))
  130. $this->mysql->cerrar();
  131.  
  132. /* Final de la ejecución */
  133. }
  134.  
  135. function detectaAgenteDeUsuario(){
  136.  
  137. /* Valores por defecto */
  138. $this->navegador = array(
  139. 'nombre' => '',
  140. 'version' => '',
  141. 'ie<=8' => false,
  142. 'soportaHTML5' => false /* ie >= 9 && * */
  143. );
  144.  
  145. /* Detecta el motor del agente de usuario */
  146. '#(?<navegador>'.join('|', array('msie', 'firefox', 'safari', 'webkit', 'opera', 'netscape', 'konqueror', 'gecko')).')[/ ]+(?<version>[0-9]+(?:\.[0-9]+)?)#',
  147. strtolower($_SERVER['HTTP_USER_AGENT']),
  148. $navegador
  149. );
  150.  
  151. if($navegador['navegador'][0]){
  152. $ieTrident = false;
  153. if(strtolower(trim($navegador['navegador'][0])) == 'msie'){
  154. if(count(explode('.', $navegador['version'][0])) > 1){
  155. $mVersion = explode('.', $navegador['version'][0]);
  156. if((int)$mVersion[0] < 9){ /* ie<=8 */
  157. $ieTrident = true;
  158. }
  159.  
  160. }
  161. }
  162. $this->navegador = array(
  163. 'nombre' => strtolower(trim($navegador['navegador'][0])),
  164. 'version' => trim($navegador['version'][0]),
  165. 'ie<=8' => $ieTrident, /* ie<=8 */
  166. 'soportaHTML5' => ($ieTrident ? false : true) /* ie>=9&&* */
  167. );
  168. unset($navegador, $ieTrident);
  169. }
  170. }
  171.  
  172. function cargarLibreria($namespace, $nuevo = false, $parametros = null){
  173. /* Incluye el archivo de la librería una sola ves para hacer uso de el las veces
  174. que sea necesario */
  175. include_once($this->conf->rutas['librerias']['local'].$namespace.'.php');
  176.  
  177. if($nuevo){
  178. $libreria = new $namespace($parametros);
  179.  
  180. if(!$libreria->sys)
  181. $libreria->sys = $this; /* Librería recursiva */
  182.  
  183. /* Libreria por defecto sin recursividad */
  184. if(
  185. ($namespace != 'error') and
  186. (!$libreria->error)
  187. )
  188. $libreria->error = $this->cargarLibreria('error', true);
  189.  
  190. /* Retorna la librería cargada */
  191. return $libreria;
  192.  
  193. }else{
  194. /* El objeto ya existe? */
  195. if(is_object($this->$namespace))
  196. return $this->$namespace;
  197.  
  198. $this->$namespace = new $namespace($parametros);
  199.  
  200. if(!$this->$namespace->sys)
  201. $this->$namespace->sys = $this; /* Librería recursiva */
  202.  
  203. /* Libreria por defecto sin recursividad */
  204. if(
  205. ($namespace != 'error') and
  206. (!$this->$namespace->error)
  207. )
  208. $this->$namespace->error = $this->cargarLibreria('error', true);
  209.  
  210. /* Retorna la librería cargada */
  211. return $this->$namespace;
  212. }
  213. }
  214.  
  215. function establecerAutocargas($prefijo){
  216. /* Procesa archivos */
  217. if($archivos = glob($this->conf->rutas['autocargas']['local'].$prefijo.'*.php'))
  218. foreach($archivos as $archivo)
  219. include_once($archivo);
  220. unset($archivos);
  221.  
  222. /* Procesa directorios */
  223. if($archivos = glob($this->conf->rutas['autocargas']['local'].$prefijo.'*/index.php'))
  224. foreach($archivos as $archivo)
  225. include_once($archivo);
  226. unset($archivos);
  227. }
  228.  
  229. function obtieneModulosSeleccionables($base = false){
  230. /* Crea la base de la búsqueda */
  231. if(!$base)
  232. $base = $this->conf->rutas['modulos']['local'];
  233.  
  234. $mods = array();
  235.  
  236. /* Va en busca de los módulos */
  237. foreach(glob($base.'*/index.php') as $file){
  238. $mod = explode('/', $file);
  239. if($mod = $mod[count($mod) - 2])
  240. $mods[] = $mod;
  241. unset($mod, $file);
  242. }
  243.  
  244. /* Hay módulos? */
  245. if(!$mods)
  246. return array();
  247.  
  248. /* Arreglo contenedor de la totalidad de las secciones a devolver */
  249. $totalMods = array();
  250.  
  251. /* Va en busca de los submódulos de forma recursiva */
  252. foreach($mods as $mod){
  253. $totalMods[] = $mod;
  254.  
  255. /* Tiene submódulos? */
  256. if(is_dir($base.$mod.'/submodulos')){
  257.  
  258. /* Va en busca de los submódulos */
  259. if($submods = array_filter($this->obtieneModulosSeleccionables($base.$mod.'/submodulos/'))){
  260.  
  261. /* Procesa cada submódulo */
  262. foreach($submods as $submod){
  263. $totalMods[] = $mod.'/'.$submod;
  264. unset($submod);
  265. }
  266. unset($submods);
  267. }
  268. }
  269. unset($mod);
  270. }
  271. unset($mods, $base);
  272.  
  273. /* Devuelve todas las secicones seleciconables del directorio en contexto */
  274. return (array)array_filter($totalMods);
  275. }
  276.  
  277. function cargaModulos(){
  278. /* Estructura de directorios :
  279.  
  280. Modules [dir]
  281. module-1
  282. index.php <- main
  283. assets
  284. style.css <- automatico
  285. print.css <- automatico
  286. script.js <- automatico
  287. images
  288. a.jpg
  289. b.jpg
  290. submodulos
  291. submodulo-1.1
  292. index.php <- main
  293. assets
  294. images
  295. submodulos
  296. submodulo-1.1.1
  297. submodulo-1.1.2
  298. submodulos
  299. submodulos
  300. submodulos
  301. ...
  302. submodulo-1.2
  303. ...
  304. module-2
  305. ...
  306. */
  307.  
  308. $rutaInfo = '';
  309.  
  310. /* Determina el módo en que se obtendrán los módulos */
  311. if(isset($_SERVER['PATH_INFO']))
  312. $rutaInfo = trim((string)$_SERVER['PATH_INFO'], '/');
  313.  
  314. elseif(isset($_SERVER['ORIG_PATH_INFO']))
  315. $rutaInfo = trim((string)$_SERVER['ORIG_PATH_INFO'], '/');
  316.  
  317. else
  318. $rutaInfo = trim((string)$this->conf->moduloPrincipal, '/');
  319.  
  320. /* Extirpa los nombres de archivos terminados en .html para dar información a la URL
  321. canonizada, por ejemplo: http://localhost/usuarios/resumen/juan-lobos.html?id=18 la ruta
  322. de información será: usuarios/resumen */
  323. if(substr(strtolower($rutaInfo), -5) == '.html')
  324. $rutaInfo = substr($rutaInfo, 0, strrpos($rutaInfo, '/'));
  325.  
  326. /* Crea un mapa con las posibles secciones para prevenir el LFI o el Path Traversal */
  327. if(!$this->modulosSeleccionables = $this->obtieneModulosSeleccionables())
  328. die('No hay secciones establecidas en el sistema para cargar');
  329.  
  330. /* Existe la ruta seleccionada? (Control derivado desde la solicitud del navegador) */
  331. if(!in_array($rutaInfo, $this->modulosSeleccionables))
  332. return $this->cargarModulo('estado', array('get' => array('id' => 404, 'msg' => 'La sección solicitada no existe')));
  333.  
  334. /* Transforma la ruta de información a objeto array ordenado */
  335. if(strpos($rutaInfo, '/') !== false)
  336. /* Ruta compuesta por submódulos */
  337. $rutaInfo = array_filter((array)explode('/', $rutaInfo));
  338. else
  339. /* Sin submódulos */
  340. $rutaInfo = array($rutaInfo);
  341.  
  342. /* Establece el contexto, por ejemplo principal/submodulo/submodulo/submodulo */
  343. $this->conf->modulo['contextoCompleto'] = implode('/', $rutaInfo);
  344.  
  345. /* Token verificador para prevenir que siga cargando los submódulos si un módulo retornó con la inclusión de un nuevo módulo. */
  346. $idModulo = 0;
  347. $relativo = array();
  348.  
  349. /* Procesa cada sección necesitada */
  350. foreach($rutaInfo as $modulo){
  351. if(count($this->conf->modulo['contextoHistorial']) > (int)$idModulo)
  352. break;
  353.  
  354. /* Contexto actual */
  355. $relativo[] = $modulo;
  356.  
  357. $this->cargarModulo(implode('/', $relativo));
  358.  
  359. $idModulo++;
  360. }
  361. }
  362.  
  363. function cargarModulo($rutaInfo, $variablesHTTP = null){
  364.  
  365. /* Existe la ruta seleccionada? (Control derivado desde un módulo o librería) */
  366. if(!in_array($rutaInfo, $this->modulosSeleccionables))
  367. return $this->cargarModulo('estado', array('get' => array('id' => 404, 'msg' => 'La sección solicitada no existe')));
  368.  
  369. /* Compone las variables via HTTP GET y POST */
  370. if($variablesHTTP){
  371. if(isset($variablesHTTP['get']))
  372. $_GET  = array_filter(array_merge($_GET, $variablesHTTP['get']));
  373.  
  374. if(isset($variablesHTTP['post']))
  375. $_POST = array_filter(array_merge($_POST, $variablesHTTP['post']));
  376.  
  377. unset($variablesHTTP);
  378. }
  379.  
  380. /* Limpia la ruta de información */
  381. $rutaInfo = trim(trim($rutaInfo), '/');
  382.  
  383. /* Compone la ruta real */
  384. $rutaReal = array(
  385. 'local' => $this->conf->rutas['modulos']['local'].str_replace('/', '/submodulos/', $rutaInfo).'/',
  386. 'remoto' => $this->conf->rutas['modulos']['enlace'].str_replace('/', '/submodulos/', $rutaInfo).'/',
  387. 'enlace' => $this->enlace($rutaInfo)
  388. );
  389.  
  390. /* Obtiene el identificador del módulo final */
  391. if(strpos($rutaInfo, '/') !== false){
  392. $idModulo = explode('/', $rutaInfo);
  393. $idModulo = $idModulo[count($idModulo) - 1];
  394. }else
  395. $idModulo = $rutaInfo;
  396.  
  397. /* Obtiene los datos del último módulo */
  398. $this->conf->modulo['actual'] = array(
  399. 'id' => $idModulo,
  400. 'rutaInfo' => $rutaInfo,
  401. 'titulo' => '', /* Se establecerá dentro del módulo de manera opcional */
  402. 'rutas' => $rutaReal
  403. );
  404.  
  405. /* Establece el historial de secciones llamadas (útil para crear menus de navegación) */
  406. $this->conf->modulo['historial'][] = $this->conf->modulo['actual'];
  407. $this->conf->modulo['contextoHistorial'][] = $this->conf->modulo['actual']['rutaInfo'];
  408.  
  409. /* Elimina todo contenido anterior al módulo */
  410. unset($b);
  411.  
  412. /* Inicia el capturado del contenido del módulo */
  413.  
  414. /* Incluye la sección */
  415. include_once($rutaReal['local'].'index.php');
  416.  
  417. /* Obtiene el contenodo del módulo */
  418. $this->contenidoHtml['modulo'][] = ob_get_contents();
  419.  
  420. /* Incluye dependencias de forma automática (evita tener que declararlas en cada sección) */
  421. if(file_exists($rutaReal['local'].'/assets/script.js'))
  422. $this->contenidoHtml['cabecera'] .=
  423. '<script type="text/javascript">'."\n".
  424. "/*\nIncluido automáticamente desde \n".$rutaReal['remoto']."assets/script.js\n*/\n\n".
  425. file_get_contents($rutaReal['local'].'assets/script.js')."\n".
  426. '</script>'."\n";
  427.  
  428. if(file_exists($rutaReal['local'].'/assets/style.css'))
  429. $this->contenidoHtml['cabecera'] .=
  430. '<style type="text/css" media="all">'."\n".
  431. "/*\nIncluido automáticamente desde \n".$rutaReal['remoto']."assets/style.css\n*/\n\n".
  432. file_get_contents($rutaReal['local'].'assets/style.css')."\n".
  433. '</style>'."\n";
  434.  
  435. if(file_exists($rutaReal['local'].'/assets/print.css'))
  436. $this->contenidoHtml['cabecera'] .=
  437. '<style type="text/css" media="print">'."\n".
  438. "/*\nIncluido automáticamente desde \n".$rutaReal['remoto']."assets/print.css\n*/\n\n".
  439. file_get_contents($rutaReal['local'].'assets/print.css')."\n".
  440. '</style>'."\n";
  441.  
  442. /* Actualiza los datos establecidos por el módulo */
  443. $this->conf->modulo['historial'][count($this->conf->modulo['historial']) - 1] = $this->conf->modulo['actual'];
  444. }
  445.  
  446. function enlace($rutaInfo = null, $parametros = null, $informacion = null){
  447. $ruta = $this->conf->rutas['base']['enlace'];
  448.  
  449. /* Si no hay ruta lo enlaza al directorio raiz */
  450. if($rutaInfo)
  451. $ruta .= trim($rutaInfo, '/').'/';
  452.  
  453. /* Archivo .html que se mostrará al final de la ruta del enlace */
  454. if($informacion)
  455. $ruta .= urlencode($this->str->toFriendlyUrl($informacion)).'.html';
  456.  
  457. /* Parámetros vía HTTP GET */
  458. if($parametros)
  459. $ruta .= '?'.$parametros;
  460.  
  461. return $ruta;
  462. }
  463.  
  464. function redireccionaEnlace($rutaInfo = null, $parametros = null, $informacion = null){
  465. return $this->cabeceras->redireccionaUrl($this->enlace($rutaInfo, $parametros, $informacion));
  466. }
  467. }
  468.  


Título: Re: crear enlaces seguros para las paginas php
Publicado por: WHK en 25 Septiembre 2014, 20:01 pm
    preg_match('/^([\w\/]+)=?(\w+)?&?/', $_SERVER['QUERY_STRING'], $matches);
     
    if(array_key_exists($matches[0], $includes)){

Talves ese código pueda ser vulnerable a un RE-DOS (denial of service in Expression Regular), por ejemplo tienes una llamada redundante si te escribo esta url:

demo/index.php/////////////// ... //////////////?&======&=&=&=&&&&&&&&&&& ...

Tu expresión puede causar que retorne nulo o que la función arroje alugn tipo de excepción especialmente por el array_key_exists ya que $matches[0] no existiría y puedes provocar un agujero de tipo path disclosure.


Título: Re: crear enlaces seguros para las paginas php
Publicado por: MinusFour en 25 Septiembre 2014, 21:24 pm
Talves ese código pueda ser vulnerable a un RE-DOS (denial of service in expression Regular), por ejemplo tienes una llamada redundante si te escribo esta url:

demo/index.php/////////////// ... //////////////?&======&=&=&=&&&&&&&&&&& ...

Tu expresión puede causar que retorne nulo o que la función arroje alugn tipo de excepción especialmente por el array_key_exists ya que $matches[0] no existiría y puedes provocar un agujero de tipo path disclosure.

Pues a mi esas urls no me tiran ningun problema, incluso tirando URLs enormes. ¿En que parte de mi REGEX dices que puede haber una redundancia?

Si el OP se siente a disgusto con mi REGEX, pues se puede hacer otra cosa como:

Código
  1. foreach ($includes as $key => $val){
  2. if(preg_match("@^$key@", $_SERVER["QUERY_STRING"])){
  3. echo $val;
  4. }
  5. }

Y si el indice 0 no existe, devuelve un notice pero array_key_exists devuelve false así que lo que ponga dentro del bloque nunca llega a ejecutarse y array_key_exists no devuelve ninguna excepción, error, notice o warning.

De todas formas, es buena idea comprobar si el valor existe, solo por si algunas otras versiones de PHP se comportan de otra manera.

Esa era la idea en un principio, ahora mismo lo mas cercano a eso que tengo es:

Código:
www.sitio.com/?site/login

Y me gustaría poder hacer eso que comentas... ¿Podrias decirme como podria hacerlo con el mod_rewrite? Ya tengo un .htaccess preparado :)

Pero volviendo al otro problema, es posible hacer que el codigo actual solo lea hasta & y apartir se interprete como otra variable? Para poder hacer que funcione ?site/login&error=1

Gracias!

Ok, tenía un pequeño error con el $match, pero esto debería regresar la primera palabra antes del =&.

Código
  1. $views = 'views/';
  2. $site = $views . 'site/';
  3. $user = $views . 'user/';
  4.  
  5. $time = microtime(true);
  6.  
  7. $includes = array(
  8. 'home' => $views . 'home.php',
  9. 'site/login' => $site . 'login.php',
  10. 'site/logout' => $site . 'logout.php',
  11. 'site/contact' => $site . 'contact.php',
  12. 'site/about' => $site . 'about.php',
  13. 'user/register' => $user . 'register.php',
  14. 'user/referral' => $user . 'referral.php',
  15. 'user/friend' => $user. 'friend.php',
  16. 'user/register_success' => $user . 'register_success.php'
  17. );
  18.  
  19. preg_match('/^([\w\/]+)=?(\w+)?&?/', $_SERVER['QUERY_STRING'], $matches);
  20. $matches[1] = isset($matches[1]) ? $matches[1] : null;
  21.  
  22. if(array_key_exists($matches[1], $includes)){
  23. echo $includes[$matches[1]];
  24.  
  25. }

En cuanto a lo del ruteador, ya es preferencia si eliges crearte tu propio ruteador o usar el de otros. No necesitas cargarte todo un framework para implementar un ruteador, puedes usar por ejemplo una libreria:

https://github.com/dannyvankooten/PHP-Router


Título: Re: crear enlaces seguros para las paginas php
Publicado por: gAb1 en 25 Septiembre 2014, 23:03 pm
@WHK Gracias, el proyecto actual tengo pensado hacer algo ligero, nada de frameworks o librerias. Ademas de que hacer la web de 0 me ayudara a ganar experiencia en este lenguaje. Pero si no te importa me guardo el codigo, seguramente vaya a necesitarlo para algo más grande :)

Siempre y cuando lo que vaya hacer en la web no requiera nada externo como librerias o plugins, y de momento no es necesario.

@MinusFour Gracias a ti tambien por las molestias! Por cierto, ¿para que es la variable $time que has puesto en el codigo? Se te habia olvidado poner la funcion include() al final, pero ya esta todo funcionando! :D

Código
  1. function showContent() {
  2. $views = 'views/';
  3. $site = $views . 'site/';
  4. $user = $views . 'user/';
  5.  
  6. //$time = microtime(true);       // Para que sirve esto??
  7.  
  8. //$_SERVER['QUERY_STRING'] = 'home';   // Como hago para mostrar home aunque no se haga un input??
  9.  
  10. $includes = array(
  11. 'home' => $views . 'home.php',
  12. 'site/login' => $site . 'login.php',
  13. 'site/logout' => $site . 'logout.php',
  14. 'site/contact' => $site . 'contact.php',
  15. 'site/about' => $site . 'about.php',
  16. 'user/register' => $user . 'register.php',
  17. 'user/referral' => $user . 'referral.php',
  18. 'user/friend' => $user. 'friend.php',
  19. 'user/register_success' => $user . 'register_success.php'
  20. );
  21.  
  22. preg_match('/^([\w\/]+)=?(\w+)?&?/', $_SERVER['QUERY_STRING'], $matches);
  23. $matches[1] = isset($matches[1]) ? $matches[1] : null;
  24.  
  25. if(array_key_exists($matches[1], $includes)){
  26. $content = include($includes[$matches[1]]);
  27. return $content;
  28. }

Y dentro de main.php simplemento llamo a la función showContent() aunque he tenido que incluir index.php Y seguro que se puede arreglar la manera de hacerlo... hehehe

Código
  1. <?php
  2. $path = $_SERVER['DOCUMENT_ROOT'];
  3. $path .= "/index.php";
  4. include_once($path);
  5. showContent();
  6. ?>

Y todavia estoy tratando de averiguar como hacer que home sea lo que se muestra cuando no hay un input: index.php incluye main.php y este home.php.

Gracias!

Edito: Estoy algo espeso... con la solución delante todo el tiempo y no la veia :P

Código
  1. if(!$_SERVER['QUERY_STRING'])
  2.    $_SERVER['QUERY_STRING'] = 'home';


Título: Re: crear enlaces seguros para las paginas php
Publicado por: MinusFour en 25 Septiembre 2014, 23:28 pm
La variable $time, la estaba usando para hacer pruebas, al final volvia a hacer microtime() y restaba para saber cuanto tardaba en ejecutar el código.

¿Te refieres a cargar la ruta home cuando QUERY_STRING este vacio?
Código
  1. if(array_key_exists($matches[1], $includes)){
  2. $content = include($includes[$matches[1]]);
  3. } elseif (empty($_SERVER['QUERY_STRING'])){
  4.        $content = include($includes['home']);
  5.        } else {
  6.        $content = "Error 404";
  7.        }
  8. return $content;
  9.  


Título: Re: crear enlaces seguros para las paginas php
Publicado por: gAb1 en 25 Septiembre 2014, 23:30 pm
Y volviendo a lo de las rutas de enlace, ¿seria muy dificil con el codigo actual no necesitar "?" para llamar una pagina?


Título: Re: crear enlaces seguros para las paginas php
Publicado por: MinusFour en 25 Septiembre 2014, 23:46 pm
Y volviendo a lo de las rutas de enlace, ¿seria muy dificil con el codigo actual no necesitar "?" para llamar una pagina?

No es díficil, lo que hacen casi todos los ruteadores de los scripts/frameworks famosos como Wordpress, Joomla, Symfony, Zend, etc. Es redirigir todas las direcciones a un archivo de entrada (por medio de mod_rewrite) y luego parsean la dirección y despliegan el recurso necesario.

Por ejemplo:

Código:
http://pagina.com/hola
http://pagina.com/categoria
http://pagina.com/test

Por medio de un mod_rewrite haces que todas las urls redirigan a entry.php por ejemplo.

Desde el entry.php tu puedes manejar las urls y desplegar la información de acuerdo al REQUEST_URI.

Código
  1.  
  2. if($_SERVER['REQUEST_URI'] == '/hola'){
  3.   //Muestra el contenido de http://pagina.com/hola
  4. } elseif($_SERVER['REQUEST_URI'] == '/categoria') {
  5.  //Muestra el contenido de http://pagina.com/categoria
  6. } else {
  7.  //Ruta no econtrada: error 404
  8. }


Título: Re: crear enlaces seguros para las paginas php
Publicado por: WHK en 25 Septiembre 2014, 23:48 pm
Codeigniter es el framework mas robusto y liviano que existe, las paginas se ejecutan en 0.001 segundos aprox y no tienes que preocuparte por estas cosas.

De todas formas el proyecto es tuyo y tu sabes que haces con el.

Si no quieres usar "?" puedes pasar los parámetros así: index.php/parametros/test de todas formas codeigniter también hace eso para el seo y los permalinks y el codigo de ejemplo que te di tambien lo hace.

Código
  1. if(isset($_SERVER['PATH_INFO']))
  2. $rutaInfo = trim((string)$_SERVER['PATH_INFO'], '/');
  3.  
  4. elseif(isset($_SERVER['ORIG_PATH_INFO']))
  5. $rutaInfo = trim((string)$_SERVER['ORIG_PATH_INFO'], '/');

Después ocultas el index.php con un htaccess y no necesitas crear reglas raras via htaccess como lo hace wordpress o joomla. Te ahorras tener que tocar esos archivos cada ves que tengas secciones nuevas.


Título: Re: crear enlaces seguros para las paginas php
Publicado por: MinusFour en 26 Septiembre 2014, 01:06 am
Te ahorras tener que tocar esos archivos cada ves que tengas secciones nuevas.

No necesitas tocar los .htaccess para nada, con las reglas por default de wordpress te bastan. El ruteador hace todo por tí.. y las reglas del mod_rewrite pueden ser tan sencillas como:

Código
  1. DirectoryIndex entry.php
  2.  
  3. <IfModule mod_rewrite.c>
  4. RewriteEngine On
  5. RewriteBase /
  6. RewriteRule ^entry\.php$ - [L]
  7. RewriteCond %{REQUEST_FILENAME} !-f
  8. RewriteCond %{REQUEST_FILENAME} !-d
  9. RewriteRule . /entry.php [L]
  10. </IfModule>

Y no necesitas modificar tus rutas para nada en el .htaccess, las modificas en el archivo entry.php

Código
  1. <?php
  2.  
  3. $string = $_SERVER['REQUEST_URI'];
  4.  
  5. if($string == '/hola'){
  6. echo 'hey';
  7. }
  8. elseif($string == '/test'){
  9. echo 'test';
  10. }
  11. elseif($string == '/hey'){
  12. echo 'hrm';
  13. }
  14. elseif($string == '/'){
  15. echo 'home';
  16. } else {
  17. echo 'Error 404';
  18. }
  19.  
  20. ?>


Título: Re: crear enlaces seguros para las paginas php
Publicado por: gAb1 en 26 Septiembre 2014, 01:49 am
Vaya, dos maneras diferentes... Me gustaría probar las dos para ver que tal, pero tengo algunas dudas:

1º ¿Donde tengo que poner este codigo? Perdonar mi ignorancia :P

Código
  1.    if(isset($_SERVER['PATH_INFO']))
  2.    $rutaInfo = trim((string)$_SERVER['PATH_INFO'], '/');
  3.  
  4.    elseif(isset($_SERVER['ORIG_PATH_INFO']))
  5.    $rutaInfo = trim((string)$_SERVER['ORIG_PATH_INFO'], '/');

2º El metodo redirigiendo a entry.php,  que pasa en el caso de usar un archivo.php que existe para usar un link? Por ejemplo, si test.php existe y escribo test.php/site/login: daria error, no?

Porque cualquier cosa que escribas se redirige a entry.php y se compara con la lista? O solo se compara lo que hay despues de ?, o de esta manera se compara todo lo que escribas despues de la url? awww.site.com/'---> a partir de aqui se compara todo?

Volvemos a lo de antes, que pasa con las variables como login.php?error=1?? se seguirian ejecutando? site.com/site/login&error=1?

Gracias!


Título: Re: crear enlaces seguros para las paginas php
Publicado por: MinusFour en 26 Septiembre 2014, 02:11 am
Si test.php existe y escribes test.php/site/login, se ejecuta test.php, pero el URI cambia, ya no es /site/login ahora es /test.php/site/login. Claro que si tu script no está leyendo el URI o el path, no afecta en nada.

Para el queryString puede ser un problema, porque no hace un match exacto con la ruta. PATH_INFO sería una solución más adecuada si quieres conservar el QueryString o hacer alguna manipulación de texto con el REQUEST_URI. También puedes optar por "reescribir" tu queryString dentro de una ruta.

Por ejemplo:

Código:
/site/login/error/1


Título: Re: crear enlaces seguros para las paginas php
Publicado por: gAb1 en 26 Septiembre 2014, 02:29 am
¿Por que no funciona esto?

Código
  1. preg_match('/^([\w\/]+)=?(\w+)?&?/', $_SERVER['REQUEST_URI'], $matches);
  2. $matches[1] = isset($matches[1]) ? $matches[1] : null;

Es más complicado de lo que parece porque index.php es lo que llama la estructura y esta llama los views. Si se cambia de pagina ya no funcionaria...

Lo intento de ese modo porque me gustaría tener el tipo de links -> site.com/site/login&error=1 y que funcionara.


Título: Re: crear enlaces seguros para las paginas php
Publicado por: MinusFour en 26 Septiembre 2014, 02:46 am
¿Por que no funciona esto?

Código
  1. preg_match('/^([\w\/]+)=?(\w+)?&?/', $_SERVER['REQUEST_URI'], $matches);
  2. $matches[1] = isset($matches[1]) ? $matches[1] : null;

Es más complicado de lo que parece porque index.php es lo que llama la estructura y esta llama los views. Si se cambia de pagina ya no funcionaria...

Lo intento de ese modo porque me gustaría tener el tipo de links -> site.com/site/login&error=1 y que funcionara.

Te refieres a:
Código:
site.com/site/login?error=1

No te va a funcionoar el regex.
Código
  1. $_SERVER['REQUEST_URI']
tiene un valor de
Código:
/site/login?error=1
Lo que podrías hacer es algo como lo que puse antes:

Código
  1. foreach ($includes as $key => $val){
  2. if(preg_match("@^/$key@", $_SERVER["REQUEST_URI"])){
  3. include $val;
  4. }
  5. }


Título: Re: crear enlaces seguros para las paginas php
Publicado por: gAb1 en 26 Septiembre 2014, 04:34 am
Lo siento fallo mio, si que funcionaba, se me olvido el .htaccess

Lo unico es que en lugar de entry.php uso index.php.

Código
  1. function showContent() {
  2. $views = 'views/';
  3. $site = $views . 'site/';
  4. $user = $views . 'user/';
  5.  
  6. if($_SERVER['REQUEST_URI'] == '/')
  7. $_SERVER['REQUEST_URI'] = '/home';
  8.  
  9. $includes = array(
  10. '/home' => $views . 'home.php',
  11. '/login' => $site . 'login.php',
  12. '/logout' => $site . 'logout.php',
  13. '/contact' => $site . 'contact.php',
  14. '/about' => $site . 'about.php',
  15. '/register' => $user . 'register.php',
  16. '/referral' => $user . 'referral.php',
  17. '/friend' => $user . 'friend.php',
  18. '/register_success' => $user . 'register_success.php'
  19. );
  20.  
  21. preg_match('/^([\w\/]+)=?(\w+)?&?/', $_SERVER['REQUEST_URI'], $matches);
  22. $matches[1] = isset($matches[1]) ? $matches[1] : null;
  23.  
  24. if(array_key_exists($matches[1], $includes)){
  25. $content = include($includes[$matches[1]]);
  26. } else $content = "Error 404";
  27. return $content;
  28. }
  29.  

Y efectivamente los links son: site.com/login?error=1

Al final de la manera mas simple posible, directamente el nombre del archivo, sin carpeta.

¿Podrías decirme alguna manera de comprobar si es vulnerable? Como por ejemplo lo de poner una larga cadena de caracteres y crear agujeros de esos. ¿O no se puede si hay una whitelist?


Título: Re: crear enlaces seguros para las paginas php
Publicado por: MinusFour en 26 Septiembre 2014, 05:10 am
Bueno, la expresión regular si te va a capturar la parte que necesitas, pero lo demás realmente es innecesario. De hecho, ahora que me pongo a pensar un poco en mi expresión, realmente no necesitas el "?=(\w+)?&?' para nada, está de más.

También podrias adaptar la expresión regular para que funcione através del archivo.php. Como lo tienes ahora:

Código:
http://www.site.com/inicio
//Funciona

http://www.site.com/index.php/inicio
//No funciona


Título: Re: crear enlaces seguros para las paginas php
Publicado por: gAb1 en 26 Septiembre 2014, 05:38 am
¿Te refieres a que funcionen los links con el index.php? Si es eso, es justo lo que no queria, usar nombres completos, el objetivo era este, con un simple nombre sin extension llamar la pagina.

Asi tal cual lo tengo funciona perfectamente.


Título: Re: crear enlaces seguros para las paginas php
Publicado por: JorgeEMX en 29 Septiembre 2014, 06:15 am
Sería más simple irse por lo que debería ser que estar evitando lo que no. Como se supone que debería de ser es, cualquier inclusión que se vaya hacer se parte de un directorio padre y común para iniciar. A éste directorio padre lo único que podría incluir es un archivo o más directorios, y archivos. Por regla general, los nombres de estos archivos y directorios sólo puede ser nombrados por letras de la A-Z y por mucho usar - y _ (/ para delimitar directorios). Cualquier otro carácter se omite y se parte de ahí para incluir cualquier cosa hacía adelante del directorio padre (nunca hacía atrás y mucho menos de algún otro origen que no sea el sistema de ficheros actual). Esto pensando que el "ruteo" sea del tipo /uno/dos/tres. Después sólo bastaría confirmar que el archivo exista.

Una disculpa si no pongo un ejemplo pero sólo paso por acá un rato y ya es de noche (me estoy haciendo viejo). Lo que es cierto es que ya hay bastante proyectos robustos que serían fácil de implementar y evitar reinventar la rueda como bien te comentaron.


Título: Re: crear enlaces seguros para las paginas php
Publicado por: WHK en 29 Septiembre 2014, 14:03 pm
Citar
Sería más simple irse por lo que debería ser que estar evitando lo que no. Como se supone que debería de ser es

Permitir solo de la A a la Z mas - y _ no es irse por lo que debería ser, de hecho te contradices en parte ya que con ese filtro te estás saliendo de norma, que tal si una carpeta se llama por ejemplo admin.mensajes ? según tu modelo dejará de funcionar. Tanto en los sistemas Unix como Linux y Windows tienen diferentes estándares en cuanto a que carácter es permitido como nombre de carpeta y nombre de archivo, por lo cual si tu haces un desarrollo no estandarizado omitiendo caracteres que si están permitidos por el sistema entonces dejará de ser una aplicación escalable ya que otros desarrolladores o el mismo administrador del sistema no podrá utilizar el sistema de archivos común del mismo sistema operativo. Recuerda que un directorio o archivo puede incluir incluso caracteres como acentos, espacios en blanco, puntos, signos especiales, paréntesis, arrobas, etc.

Bajo este contexto mi modelo es el mas eficiente porque cumple con todos los estándares de posibles reales carpetas y archivos bajo una lista blanca como únicos permitidos y sin la necesidad de tener que modificar el código si agregas secciones nuevas, tampoco usa expresiones regulares, o sea, usa menos memoria, menos cpu, menos lineas de código, no es vulnerable, o sea tal como dijiste tu, irse por lo que debería ser en ves de estar evitando lo que no es, no se porque aun le dan tantas vueltas al tema buscando opciones menos inseguras, mas pesadas y con problemas de seguridad.


Título: Re: crear enlaces seguros para las paginas php
Publicado por: JorgeEMX en 29 Septiembre 2014, 15:41 pm
Permitir solo de la A a la Z mas - y _ no es irse por lo que debería ser, de hecho te contradices en parte ya que con ese filtro te estás saliendo de norma, que tal si una carpeta se llama por ejemplo admin.mensajes ? según tu modelo dejará de funcionar. Tanto en los sistemas Unix como Linux y Windows tienen diferentes estándares en cuanto a que carácter es permitido como nombre de carpeta y nombre de archivo, por lo cual si tu haces un desarrollo no estandarizado omitiendo caracteres que si están permitidos por el sistema entonces dejará de ser una aplicación escalable ya que otros desarrolladores o el mismo administrador del sistema no podrá utilizar el sistema de archivos común del mismo sistema operativo. Recuerda que un directorio o archivo puede incluir incluso caracteres como acentos, espacios en blanco, puntos, signos especiales, paréntesis, arrobas, etc.

Te doy la razón y por eso dije algo como:

Esto pensando que el "ruteo" sea del tipo /uno/dos/tres.

Y el creador del tema si quiere algo en especifico y no algo tan flexible que vaya a exponer como público para la comunidad. Si tú script funciona con la misma lógica pero siendo más flexible entonces también ya lo tiene hecho.

Saludos


Título: Re: crear enlaces seguros para las paginas php
Publicado por: MinusFour en 29 Septiembre 2014, 16:14 pm
Las rutas no necesitan seguir las convenciones de nombrado del sistema de archivos unix o win. Las URIs se apegan a: http://tools.ietf.org/html/rfc3986 y tecnicamente no necesita usarse REGEX, con un simple strpos le bastaría, pero así no tiene que estar ciclando por todo el arreglo.