Foros del Web » Programando para Internet » PHP »

PHP OO [Aporte] Clase para comprobar datos de un GET entre páginas

Estas en el tema de [Aporte] Clase para comprobar datos de un GET entre páginas en el foro de PHP en Foros del Web. He creado una clase en PHP para comprobar que los pares de clave y valor de un GET a los que enlazamos en un una ...
  #1 (permalink)  
Antiguo 10/01/2012, 06:35
 
Fecha de Ingreso: octubre-2004
Ubicación: Barcelona
Mensajes: 195
Antigüedad: 19 años, 6 meses
Puntos: 7
[Aporte] Clase para comprobar datos de un GET entre páginas

He creado una clase en PHP para comprobar que los pares de clave y valor de un GET a los que enlazamos en un una página no han sido modificados por el usuario en la barra de direcciones del navegador en la página de destino.

Puede ser útil, por ejemplo, cuando queremos dar listas con soluciones a ejercicios a medida que avanza un curso. Con unos pares solucion / tema para que si una combinacion de número de solucion y tema no esta en lista de la pagina in¡cial no pueda ser visto por el usuario utilizando la barra de direcciones. También se puede cambiar la clave para cada usuario para identificar los que intentan saltarse la proteccion o para generar links que sólo puedan ser vistos por este usuario.

La forma en que lo hace es convirtiendo con serialize en una cadena un array con los datos que irán en el GET añadiendo un elemento más con una palabra secreta. Con la cadena resultante generamos un hash MD5 que añadiremos al GET final. En la página siguiente hacemos el mismo proceso para comprobar que el GET que nos ha llegado genera la misma clave MD5.

seguridadpareshash.php
Código PHP:
<?php
/** 
 *  Seguridad GET con un hash MD5
 *    
 *  Comprueba en el script de destino que los datos de un query al que 
 *  enlaza nuestra pagina son los originales
 *    
 *  Puede ser útil, por ejemplo, cuando queremos dar listas con 
 *  soluciones a ejercicios a medida que avanza un curso. Con unos pares
 *  solucion / tema para que si una combinacion de número de solucion 
 *  y tema no esta en lista de la pagina no pueda ser visto por el 
 *  usuario utilizando la barra de direcciones. También se puede cambiar
 *  la clave para cada usuario para identificar los que intentan 
 *  saltarse la proteccion.
 *  
 *  Funciones de generacion:
 *      GeneraGETconHash -- Devuelve ?un=valor&otro=dato&sp=hash
 *      GeneraURL -- Devuelve unapagina.php?un=valor&otro=dato&sp=hash
 *      GeneraEnlace -- Devuelve <a href="unapagina.php?un=valor&otro=dato&sp=hash">Texto</a>
 *  
 *  Funcion de comprobacion:
 *      CompruebaGETconHash
 *  
*/

class CompruebaGetEntrePaginas
{    
    private 
$palabraSecreta;
    
    function 
__construct()
    {
        
$this->palabraSecreta $this->GeneraPalabraSecreta ();
    }
    
    
// Genera un GET con un codigo de comprobacion al final
    
public function GeneraGETconHash ($ArrayVariables)
    {        
        
$GETconHash "";
        
$Liga "";
        foreach (
$ArrayVariables as $UnaLlave => $UnValor){
            
$GETconHash .= $Liga.$UnaLlave."=".$UnValor;
            
$Liga "&";
        }
        
$GETconHash "?".$GETconHash;
        
$ArrayVariables["palabraSecreta"] = $this->palabraSecreta;
        
$ClaveHash hash ("md5",serialize($ArrayVariables));
        
$GETconHash .= $Liga."ps=".$ClaveHash;
        return 
$GETconHash;
    }
    
    
// Genera una URL completa, simplemente sirve para que haya menos 
    // funciones en la creación de la lista 
    
public function GeneraURL ($ElArrayVariables,$NombreScript "")
    {        
        
$elGETconHash $this->GeneraGETconHash ($ElArrayVariables);
        
$PrefijoURL = (empty($NombreScript))? $_SERVER["PHP_SELF"] : $NombreScript;
        
$URLcompleta $PrefijoURL.$elGETconHash
        return 
$URLcompleta;
    }
    
    
// Genera un enlace completo
    
public function GeneraEnlace ($ElArrayVariables,$TextoEnlace,$NombreScript ""){
        
$laURL $this->GeneraURL($ElArrayVariables,$NombreScript);
        return 
'<a href="'.$laURL.'">'.$TextoEnlace.'</a>';
    }
    
    
// Comprueba que no se ha modificado la URL
    
public function CompruebaGETconHash ()
    {
        
$ArrayTrabajo $_GET;
        
$ValorHash array_pop ($ArrayTrabajo);
        
$ArrayTrabajo["palabraSecreta"] = $this->palabraSecreta;
        
$ValorEsperadoHash hash ("md5",serialize($ArrayTrabajo));
        
$comparacionValores = ($ValorHash === $ValorEsperadoHash)? TRUE FALSE;
        return 
$comparacionValores;
    }
    
    
// Para mas seguridad se deberia reescribir esta funcion para leer el valor de una base de datos
    
private function GeneraPalabraSecreta ()
    {
        
// Este valor de retorno debe cambiarse para mas seguridad
        
return 'flghusf';
    }
}
?>
lista.php
Código PHP:
<?php
include_once ("seguridadpareshash.php");

// Iniciamos la clase de creacion/comprobacion
$CreaCompruebaURL = new CompruebaGetEntrePaginas ();

// En esta variable ponemos el nombre del script PHP. Si esta vacio
// o no esta definido se usa $_SERVER["PHP_SELF"]
$NombreScriptDestino "resultadosprueba.php";

// Datos que iran en el GET y en el texto del enlace
$DatosGet = Array("solucion" => "12","tema" => "25");
$TextoEnlace "Resultados al ejercicio 12 del tema 25";

// Mostramos el resultado en pantalla
print ($CreaCompruebaURL->GeneraEnlace ($DatosGet,$TextoEnlace,$NombreScriptDestino));
?>
resultadosprueba.php
Código PHP:
<?php
include_once ("seguridadpareshash.php");

$CreaCompruebaURL = new CompruebaGetEntrePaginas ();

// Comprobamos que coincide elcontenido de las variables de GET con el hash MD5 final
if ($CreaCompruebaURL->CompruebaGETconHash ()){
    echo 
"Datos URL originales";
} else {
    echo 
"Datos URL modificados";
}
?>
  #2 (permalink)  
Antiguo 16/01/2012, 05:59
 
Fecha de Ingreso: octubre-2004
Ubicación: Barcelona
Mensajes: 195
Antigüedad: 19 años, 6 meses
Puntos: 7
Respuesta: [Aporte] Clase para comprobar datos de un GET entre páginas

He hecho una versión bastante más depurada. Ahora funciona con una sola función para generar los datos y sólo hace falta añadir parámetros a la función para que haga más compleja la salida.

También he desarrollado la devolución del error, en este caso envía un Error 404 al navegador después de unos segundos de espera. He dejado una parte de la función que aumenta la espera a medida que se intenta saltar la protección y cambia el error devuelto a 500 aunque no sé si será de mucha utilidad ya que funciona con sesiones. La idea inicial era "luchar" contra alguna herramienta automatizada pero, aunque no soy un hacker y lo desconozco, supongo que estas herramientas deben "pasar" de las sesiones.

Por el camino he visto que Firefox (al menos Firefox 9) ya no deja cambiar los datos de un GET en la barra del navegador. Aunque sí permite copiar, pegar y modificar el enlace en otra ventana es un buen avance en seguridad.

seguridadpareshashsimple.php
Código PHP:
Ver original
  1. <?php
  2. /**
  3.  *
  4.  * Seguridad GET con un hash MD5
  5.  * 
  6.  * Comprueba en el script de destino que los datos de un query al que
  7.  * enlaza nuestra pagina son los originales
  8.  * 
  9.  * Puede ser útil, por ejemplo, cuando queremos dar listas con
  10.  * soluciones a ejercicios a medida que avanza un curso. Con unos pares
  11.  * solucion / tema para que si una combinacion de número de solucion
  12.  * y tema no esta en lista de la pagina no pueda ser visto por el
  13.  * usuario utilizando la barra de direcciones o otreo sistema.
  14.  * También se puede cambiar la clave para cada usuario para
  15.  * identificar los que intentan saltarse la proteccion.
  16.  *
  17.  * Funciones de generacion:
  18.  *  devuelveGetConHash
  19.  * @example lista.php
  20.  *
  21.  * Funcion de comprobacion:
  22.  *  compruebaGetConHash
  23.  * @example resultadosprueba.php
  24.  *
  25.  * @author Miquel-Àngel Pintanel - imaginatic.com
  26.  * @license http://opensource.org/licenses/gpl-license.php GNU Public License
  27. */
  28. class CompruebaGetEntrePaginas
  29. {  
  30.     protected $palabraSecreta;
  31.    
  32.     function __construct()
  33.     {
  34.         $this->palabraSecreta = $this->generaPalabraSecreta ();
  35.         if (!isset($_SESSION["intentoscrackeo"])){
  36.             $_SESSION["intentoscrackeo"] = 0;
  37.         }
  38.     }
  39.    
  40.     /**
  41.      *
  42.      * Genera un GET con un codigo de comprobacion al final.
  43.      * Dependiendo del número de parámetros se devuelve un GET simple, una URL
  44.      * o un enlace completo
  45.      *
  46.      * @param array $ArrayVariables Array asociativo con los datos del GET
  47.      *
  48.      * @param null|string $NombreScript Si es una cadena vacia $_SERVER["PHP_SELF"]
  49.      *
  50.      * @param null|string $TextoEnlace Texto visible del enlace
  51.      *
  52.      * @return string
  53.      */
  54.     public function devuelveGetConHash ($ArrayVariables,$NombreScript = NULL,$TextoEnlace = NULL)
  55.     {
  56.         if (is_null($NombreScript) && is_null($TextoEnlace)){
  57.             return $this->GeneraGETconHash($ArrayVariables);
  58.         } elseif (is_null($TextoEnlace)){
  59.             $elGETconHash = $this->GeneraGETconHash ($ArrayVariables);
  60.             $PrefijoURL = (empty($NombreScript))? $_SERVER["PHP_SELF"] : $NombreScript;
  61.             if (file_exists($NombreScript)){
  62.                 return $PrefijoURL.$elGETconHash;
  63.             } else {
  64.                 echo "Archivo de script $NombreScript inexistente";
  65.                 exit ();
  66.             }
  67.         } else {
  68.             $laURL = $this->GeneraURL($ArrayVariables,$NombreScript);
  69.             return '<a href="'.$laURL.'">'.$TextoEnlace.'</a>';
  70.         }
  71.     }
  72.  
  73.     /**
  74.      *
  75.      * Comprueba que no se ha modificado la URL
  76.      *
  77.      * @return bool
  78.      */
  79.     public function compruebaGetConHash ()
  80.     {
  81.         $ArrayTrabajo = $_GET;
  82.         $ValorHash = array_pop ($ArrayTrabajo);
  83.         $ArrayTrabajo["palabraSecreta"] = $this->palabraSecreta;
  84.         $ValorEsperadoHash = hash ("md5",serialize($ArrayTrabajo));
  85.         $comparacionValores = ($ValorHash === $ValorEsperadoHash)? TRUE : FALSE;
  86.         return $comparacionValores;
  87.     }
  88.    
  89.     /**
  90.      *
  91.      * Devuelve un error si hay un intento de cambiar el GET
  92.      */
  93.     public function devuelveError ()
  94.     {
  95.         if (isset($_SESSION["intentoscrackeo"])){
  96.             $intentos = $_SESSION["intentoscrackeo"];
  97.             $intentos++;
  98.             $_SESSION["intentoscrackeo"] = $intentos;
  99.             sleep(5 * $intentos);
  100.             if ($intentos < 5){
  101.                  header("HTTP/1.1 404 Not found");
  102.             } else {
  103.                 header('HTTP/1.1 500 Internal Server Error');
  104.             }
  105.         } else {
  106.             sleep(15);
  107.             header("HTTP/1.1 404 Not found");
  108.         }
  109.         $this->registraError();
  110.     }
  111.    
  112.     // Genera un GET con un codigo de comprobacion al final
  113.     protected function GeneraGETconHash ($ArrayVariables)
  114.     {
  115.         $GETconHash = "";
  116.         $Liga = "";
  117.         foreach ($ArrayVariables as $UnaLlave => $UnValor){
  118.             $GETconHash .= $Liga.$UnaLlave."=".$UnValor;
  119.             $Liga = "&";
  120.         }
  121.         $GETconHash = "?".$GETconHash;
  122.         $ArrayVariables["palabraSecreta"] = $this->palabraSecreta;
  123.         $ClaveHash = hash ("md5",serialize($ArrayVariables));
  124.         $GETconHash .= $Liga."ps=".$ClaveHash;
  125.         return $GETconHash;
  126.     }
  127.    
  128.     // Genera una URL completa, simplemente sirve para que haya menos
  129.     // funciones en la creación de la lista
  130.     protected function GeneraURL ($ElArrayVariables,$NombreScript = "")
  131.     {      
  132.         $elGETconHash = $this->GeneraGETconHash ($ElArrayVariables);
  133.         $PrefijoURL = (empty($NombreScript))? $_SERVER["PHP_SELF"] : $NombreScript;
  134.         $URLcompleta = $PrefijoURL.$elGETconHash;
  135.         return $URLcompleta;
  136.     }
  137.    
  138.     // Genera un enlace completo
  139.     protected function GeneraEnlace ($ElArrayVariables,$TextoEnlace,$NombreScript = ""){
  140.         $laURL = $this->GeneraURL($ElArrayVariables,$NombreScript);
  141.         return '<a href="'.$laURL.'">'.$TextoEnlace.'</a>';
  142.     }
  143.     /**
  144.      *
  145.      * Reescribir esta función si se quiere registrar los intentos de modificación
  146.      */
  147.     protected function registraError ()
  148.     {
  149.         return TRUE;
  150.     }
  151.    
  152.     /**
  153.      *
  154.      * Para mas seguridad se deberia reescribir esta funcion para leer el valor de una base de datos
  155.      */
  156.     protected function generaPalabraSecreta ()
  157.     {
  158.         // Este valor de retorno debe cambiarse para mas seguridad
  159.         return 'flghusf';
  160.     }
  161. }

lista.php
Código PHP:
Ver original
  1. <?php
  2. include_once ("seguridadpareshashsimple.php");
  3.  
  4. // Iniciamos la clase de creacion/comprobacion
  5. $CreaCompruebaURL = new CompruebaGetEntrePaginas ();
  6.  
  7. // En esta variable ponemos el nombre del script PHP. Si esta vacio
  8. // o no esta definido se usa $_SERVER["PHP_SELF"]
  9. $NombreScriptDestino = "resultadosprueba.php";
  10.  
  11. // Datos que iran en el GET y en el texto del enlace
  12. $DatosGet = Array("solucion" => "12","tema" => "25");
  13. $TextoEnlace = "Resultados al ejercicio 12 del tema 25";
  14.  
  15. // Mostramos el resultado en pantalla
  16. print ("<h1>Pruebas salida</h1>");
  17. print ("<h2>Solo GET</h2>");
  18. print ($CreaCompruebaURL->devuelveGetConHash ($DatosGet));
  19. print ("<h2>Solo URL</h2>");
  20. print ($CreaCompruebaURL->devuelveGetConHash ($DatosGet,$NombreScriptDestino));
  21. print "<h2>Completo</h2>";
  22. print ($CreaCompruebaURL->devuelveGetConHash ($DatosGet,$NombreScriptDestino,$TextoEnlace));

resultadosprueba.php
Código PHP:
Ver original
  1. <?php
  2. include_once ("seguridadpareshashsimple.php");
  3. $CreaCompruebaURL = new CompruebaGetEntrePaginas ();
  4.  
  5. // Comprobamos que coincide el contenido de las variables de GET con el hash MD5 final
  6. if ($CreaCompruebaURL->compruebaGetConHash () === FALSE){
  7.     $CreaCompruebaURL->devuelveError();
  8. } else {
  9.     // Aquí iría el código que muestra los datos si la comprobacion es correcta.
  10.     // En este ejemplo solo mostramos que todo ha ido bien
  11.     echo "Datos URL originales<br/>";
  12. }

Etiquetas: clase, páginas, variables, usuarios
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 10:22.