Aplica seguridad en tus formularios Cross-Site Request Forgery

Aplica seguridad en tus formularios Cross-Site Request Forgery

Tal vez te has preguntado: ¿Cómo proteger mis formularios PHP con tokens estilo CSRF?

Los tokens CSRF se utilizan para proteger formularios en PHP y evitar que un atacante pueda forzar acciones no autorizadas en nuestros formularios aun estando autenticado.

En pocas palabras Cross-Site Request Forgery nos ayuda a detener envíos de formularios falsos y ataques CSRF (Algunos programadores lo conocemos como: CSRF ó CSRF Tokens).

Ok… te lo voy a explicar con manzanas…

La Falsificación de solicitudes entre sitios (CSRF) es un ataque que obliga al usuario final a ejecutar acciones no deseadas en una aplicación web en la que está autenticado actualmente; Estos ataques CSRF se dirigen específicamente a las solicitudes que cambian el estado, no al robo de datos, ya que el atacante no tiene forma de ver la respuesta a la solicitud falsificada.

¿Cómo podría pasar que mi formulario ser victima de ataques CSRF? Con un poco de ayuda de ingeniería social (como enviar un enlace por correo electrónico o chat), un atacante puede engañar a los usuarios de una aplicación web para que ejecuten las acciones que el atacante elija.

Si la víctima es un usuario normal (un usuario que utilice nuestra aplicación), un ataque CSRF exitoso puede obligar al usuario a realizar solicitudes de cambio de estado que podría ser graves como la transferencia de fondos ó el cambio de su dirección de correo electrónico y algo mas peor aún… si la víctima es una cuenta de administrador (Upss!), el ataque CSRF puede comprometer toda la aplicación web.

Interesante No… pero un momento!! voy a explicar como aumentar la seguridad y evitar cualquier intento de ataque CSRF en dos pasos:

  1. Primero generaremos un token aleatorio y este lo almacenaremos en una variable de sesión y este token se pasará a través del formulario.
  2. Segundo después del envío del formulario, se comparará el token CSRF del formulario y el token almacenado en la sesión. Si ambos valores coinciden, solo la presentación del formulario tendrá éxito. De lo contrario, el envío del formulario será fallido.

Manos a la obra… veamos un poco codigo:

1. Generación de tokens CSRF

Primero vamos a generar el Token CSRF usando 3 funciones de PHP: rand, uniqid y md5.

Con estas 3 funciones podemos crear una cadena aleatoria (token único) que se almacenará en la sesión (en una variable de sesión para ser mas específico) y también se agregará en forma de campo de entrada oculto dentro del formulario (codigo html).

$_token = md5(uniqid(rand(), TRUE));

2. Guardamos nuestro nuevo token CSRF en una variable de Sesión

Después de crear el token único, debemos guardarlo en una variable dentro de la sesión de usuario. ¡No olvides comenzar la sesión con la función PHP!

session_start();
$_SESSION['csrf_token'] = $_token;

3. Agreguemos el token CSRF generado al formulario

¿Sabías qué? La mayoría de las personas lo hace mal… crean el Token y la almacenan en la variable y durante toda la sesión no vuelven a generarla ni actualizarla, un hacker puede notar eso y puede ser un agujero de seguridad.

El metodo correcto es generar un nuevo token cada que se haga petición de usar el formulario y actualizar el valor de la variable ($_token) en lugar del token almacenado en la sesión (refresh y un nuevo token generado, asi el hacker desistirá ya que siempre será nuevo el token).

Bueno despues de aclarar este punto, vamos a agregar un campo de entrada de formulario como un campo de entrada oculto y con el nombre de csrf_token.

Observa el código para agregar el token CSRF a tu formulario:

<input type="hidden" name="csrf_token" value="<?php echo $_token; ?>">

4. Verificaremos el token CSRF que se envía

Genial hasta aqui todo va bien… y ahora después del envío del formulario es momento de verificar el token CSRF que se envía a través del formulario y el token CSRF almacenado en la sesión.

if(isset($_POST) & !empty($_POST)){ // Comprobar el token CSRF enviado o no aquí
  if(isset($_POST['csrf_token'])){
    if($_SESSION['csrf_token'] === $_POST['csrf_token']){
      // Exito! ahora proceda con la funcionalidad de su formulario
      $msgs = "Validación de Token CSRF correcta";
    }más{
      $msgs = "Validación de CSRF Falló";
    }
  }más{
    $msgs = "Verificación de CSRF fallida";
  }
}

5. Destrucción del token CSRF

Como buena práctica debemos destruir el token CSRF que está almacenado en la sesión. Y al volver a cargar la página del formulario, este token de sesión se debería generar nuevamente y ser almacenada en la variable de sesión.

unset($_SESSION['csrf_token']);

Puedes incluirlo al final de la validación y el codigo de funcionalidad de tu formulario, quedando de esta manera:

session_start(); // si no esta declarada no olvides poner esta línea

if(isset($_POST) & !empty($_POST)){ // Comprobar el token CSRF enviado o no aquí
  if(isset($_POST['csrf_token'])){
    if($_SESSION['csrf_token'] === $_POST['csrf_token']){
      // Exito! ahora proceda con la funcionalidad de su formulario
      $msgs = "Validación de Token CSRF correcta";
    }más{
      $msgs = "Validación de CSRF Falló";
    }
  }más{
    $msgs = "Verificación de CSRF fallida";
  }
}
unset($_SESSION['csrf_token']);

Conclusión

Es muy importante considerar estas buenas practicas de verificación por la seguridad de nuestras aplicaciones web, ya que hay personas con malas intensiones que buscarán siempre brechas de seguridad en tus aplicaciones web.

¡Si necesitas ayuda con gusto puedo ayudarte en tu proyecto!

¿Te gustó este artículo? ayúdame a compartirlo.