Ver Mensaje Individual
  #64 (permalink)  
Antiguo 11/09/2013, 15:04
webankenovi
Invitado
 
Mensajes: n/a
Puntos:
Respuesta: seguridad web

CAPITULO 12

FORMULARIOS

Mi intencion con lo detallado a continuacion es orientar , no copies , explora por ti mismo , los codigos podrian tener algun error y no son un aporte , falta parte de verificaciones que en este capitulo no se detallan , tan solo es un ejemplo .

A continuacion explicare el siguiente formulario y las medidas de seguridad que lleva.

Ejemplo formulario de login:

Código HTML:
Ver original
  1. <form action="validar.php?FDW=<? echo $_SESSION['TOKEN']; ?>" method="post">
  2.  
  3. <div id="login"><input type="text" value="k_username" name="k_username" required></div>
  4. <input type="hidden" value="" name="usuario" >
  5. <input type="text" value="Introduce tu comentario"  id="comentario" name="comentario" required>
  6.  
  7. <p>Usuario:<br>
  8. <input type="text" name="<? echo $_SESSION['FORMULARIO'][$_SESSION['TOKEN']]['USUARIO']; ?> " pattern="^[a-zA-Z0-9-_]{3,15}$" maxlength="15" size="15" required></p>
  9.  
  10. <p>Password:<br>
  11. <input type="password" name="<? echo $_SESSION['FORMULARIO'][$_SESSION['TOKEN']]['PASSWORD']; ?>" pattern="(?=^.{10,30}$)((?=.*\d)(?=.*\W+))(?![.\n])(?=.*[A-Z])(?=.*[a-z]).*$" size="30" maxlength="30" required></p>
  12.  
  13. <input type="submit" value="Iniciar sesion" name="login" formenctype="application/x-www-form-urlencoded" >
  14.  
  15. </form>

Codigo fuente:

Código HTML:
Ver original
  1. <form action="validar.php?FDW=8ce3eaa2695cb5d2e7edab515dd9e8b7cd7d4278cf2681cb16b6443d105ba361/1378930760" method="post">
  2.  
  3. <div id="login"><input type="text" value="k_username" name="k_username" required></div>
  4. <input type="hidden" value="" name="usuario" required>
  5. <input type="text" value="Introduce tu comentario"  id="comentario" name="comentario" required>
  6.  
  7. <p>Usuario:<br>
  8. <input type="text" name="165414168" pattern="^[a-zA-Z0-9-_]{3,20}$" maxlength="20" size="20" required></p>
  9.  
  10. <p>Password:<br>
  11. <input type="password" name="847424868" pattern="(?=^.{10,20}$)((?=.*\d)(?=.*\W+))(?![.\n])(?=.*[A-Z])(?=.*[a-z]).*$" size="20" maxlength="20" required></p>
  12.  
  13. <input type="submit" value="Iniciar sesion" name="login" formenctype="application/x-www-form-urlencoded" >
  14.  
  15. </form>

Se puede apreciar varias cosas , entremos en detalle.


PROCEDENCIA


Vamos a usar lo visto en el capitulo 10 cross site request forgery.

Creamos una session con un hash y tambien enviamos en el action por get el token y despues lo comparamos.
Código PHP:
Ver original
  1. <? $_SESSION['TOKEN'] = hash('haval256,5',rand(),false); ?>
  2.  
  3. <form action="validar.php?FDW=<? echo $_SESSION['TOKEN']; ?>" method="post">
  4.  
  5. <input type="submit" value="Iniciar sesion" name="login" formenctype="application/x-www-form-urlencoded" >

lado del servidor:

Verificamos de donde vino el usuario , donde la url deberia de ser la url de la pagina del formulario en este caso 'http://localhost/login/' .

Código PHP:
Ver original
  1. if( empty($_SERVER['HTTP_REFERER']) || $_SERVER['HTTP_REFERER'] === 'http://localhost/login/')
  2. {
  3.     header('location:index.php');
  4.     exit();
  5.  
  6.     // esta  verificacion no es segura el referer se puede modificar
  7. }
Verificamos el token y comprobamos si existen datos del formulario login

Código PHP:
Ver original
  1. if(!empty($_SESSION['TOKEN']) and !empty($_GET['FDW']) and $_GET['FDW'] === $_SESSION['TOKEN'])
  2. {
  3.     if(isset($_POST['login']) and $_POST['login'] === 'Iniciar sesion')
  4.     {
  5.         // CONTINUAMOS

PROTEGIENDO LOS CAMPOS CLAVE

Creamos una session con los campos clave del formulario , en el formulario no mostraremos ni user ni passwor mas bien numeros aleatorios que identifican al campo y lo relacionan con la session.

Código PHP:
Ver original
  1. $_SESSION['FORMULARIO'][$_SESSION['TOKEN']] = array(
  2.  
  3.     'USUARIO' => rand(1,9999999999),
  4.     'PASSWORD' => rand(1,9999999999)
  5.  
  6.     );

$_SESSION['FORMULARIO'][$_SESSION['TOKEN']] el token es el identificador de la session del formulario , para despues acceder a los datos no servira con un simple $_POST['user'] debera de ser $_SESSION['FORMULARIO'][$_SESSION['TOKEN']][$_POST['user']]


Código PHP:
Ver original
  1. <form action="validar.php?FDW=<? echo $_SESSION['TOKEN']; ?>" method="post">
  2.  
  3.     <p>Usuario:<br>
  4.     <input type="text" name="<? echo $_SESSION['FORMULARIO'][$_SESSION['TOKEN']]['USUARIO']; ?>" pattern="^[a-zA-Z0-9-_]{3,15}$" maxlength="15" size="15" required></p>
  5.  
  6.     <p>Password:<br>
  7.     <input type="password" name="<? echo $_SESSION['FORMULARIO'][$_SESSION['TOKEN']]['PASSWORD']; ?>" pattern="(?=^.{10,30}$)((?=.*\d)(?=.*\W+))(?![.\n])(?=.*[A-Z])(?=.*[a-z]).*$" size="30" maxlength="30" required></p>
  8.  
  9.     <input type="submit" value="Iniciar sesion" name="login" formenctype="application/x-www-form-urlencoded" >
  10.  
  11.     </form>

lado del servidor:

Código PHP:
Ver original
  1. $user        = $_SESSION['FORMULARIO'][$_GET['FDW']]['USUARIO'];
  2. $password = $_SESSION['FORMULARIO'][$_GET['FDW']]['PASSWORD'];
  3.  
  4. if(!empty($_POST[$user]) and !empty($_POST[$password]))
  5. {
  6.     // CONTINUAMOS
  7.     // para acceder a los datos $_POST[$user] $_POST[$password] , $user y $password identifican el campo del formulario
  8. }
  9. else
  10. {
  11. // existe algun campo vacio o no es valido como null , 0 , false etc.......
  12. }

EXPRESIONES REGULARES

Solo se aceptaran usuarios con letras mayusculas/minusculas numeros y guion bajo _ y guion - minimo 3 caracteres y maximo 15 caracteres , este input es requerido.

pattern="^[a-zA-Z0-9-_]{3,15}$"

Código HTML:
Ver original
  1. <p>Usuario:<br>
  2. <input type="text" name="<? echo $_SESSION['FORMULARIO'][$_SESSION['TOKEN']]['USUARIO']; ?>" pattern="^[a-zA-Z0-9-_]{3,15}$" maxlength="15" size="15" required></p>

El password debe de contener al menos una mayucula una minuscula un numero un caracter especial y minimo 10 caracteres maximo 30 caracteres , este input es requerido.

pattern="(?=^.{10,30}$)((?=.*\d)(?=.*\W+))(?![.\n])(?=.*[A-Z])(?=.*[a-z]).*$"

Código HTML:
Ver original
  1. <p>Password:<br>
  2. <input type="password" name="<? echo $_SESSION['FORMULARIO'][$_SESSION['TOKEN']]['USUARIO']; ?>" pattern="(?=^.{10,30}$)((?=.*\d)(?=.*\W+))(?![.\n])(?=.*[A-Z])(?=.*[a-z]).*$" size="30" maxlength="30" required></p>

Esta medida de seguridad es altamente saltable ya que se puede modificar el codigo html y saltarse la verificacion, por ello debemos verificar en el lado del servidor.

lado del servidor:

Código PHP:
Ver original
  1. if(!empty($_POST[$user]))
  2. {
  3.     if(strlen($_POST[$user]) >= 3 and strlen($_POST[$user]) <= 15)
  4.     {
  5.         if( preg_match('|^[a-zA-Z0-9-_]{3,15}$|', $_POST[$user], $coincidencias) !== 1 )
  6.         {
  7.             exit('usuario no valido');
  8.         }
  9.     }
  10.     else
  11.     {
  12.         exit('longitud no valida');    
  13.     }
  14. }
  15. else
  16. {
  17.     exit('debe de rellenar todos los datos');
  18. }
  19.  
  20.  
  21. if(!empty($_POST[$password]))
  22. {
  23.     if(strlen($_POST[$password]) >= 10 and strlen($_POST[$password]) <= 30)
  24.     {
  25.         if( preg_match('|(?=^.{10,30}$)((?=.*\d)(?=.*\W+))(?![.\n])(?=.*[A-Z])(?=.*[a-z]).*$|', $_POST[$password], $coincidencias) !== 1 )
  26.         {
  27.             exit('password no valido');
  28.         }
  29.     }
  30.     else
  31.     {
  32.         exit('longitud no valida');    
  33.     }
  34. }
  35. else
  36. {
  37.     exit('debe de rellenar todos los datos');
  38. }

ANTIBOTS

Ocultaremos campos como se hablo en el capitulo 11 , añadiendo un campo escondido en un div oculto.

Código CSS:
Ver original
  1. <style>
  2.  
  3. input#comentario,#login { display:none; }
  4.  
  5. </style>

Código HTML:
Ver original
  1. <div id="login"><input type="text" value="k_username" name="k_username" required></div>
  2.  
  3.     <input type="hidden" value="" name="usuario" >
  4.  
  5.     <input type="text" value="Introduce tu comentario"  id="comentario" name="comentario" required>
lado del servidor:

Código PHP:
Ver original
  1. if(empty($_POST['usuario']) and isset($_POST['comentario']) and $_POST['comentario'] === 'Introduce tu comentario' and !empty($_POST['k_username']) and $_POST['k_username'] === 'k_username' )
  2. {
  3.     // continuamos
  4. }
  5. else
  6. {
  7.     // bot
  8. }

Parte 2 A continuacion