Protección CSRF en WordPress
La protección CSRF en WordPress es la que nos permite hacer un formulario seguro en para una página, una sección, un artículo, etc; y esta tiene bastante importancia. Ya paso largo tiempo en que WordPress se utilizaba solo para escribir lo que pensamos o que queremos compartir con el lector.
Tenga en cuenta que el usuario al menos necesitara hacer una búsqueda como en este sitio, este blog tiende a publicar cosas que me parecen interesantes o que puedan ayudar a otros, por eso es que solo tiene una búsqueda.
Pero si usted está interesado en crear formularios sin que su WordPress termine siendo hackeado o sufriendo ataques XSS deberá utilizar varias funciones de WordPress en su plug-in o theme.
Estas funciones son wp_nonce_field
, wp_verify_nonce
y check_admin_referer
.
Función wp_nonce_field
https://blastcoding.com/proteccion-csrf-en-wordpress/#wp_nonce_fieldEsta función devolverá un hidden field para los formularios, puede o no mostrarlo dependiendo del cuarto parámetro si es true
o es false
. En caso de que este parámetro sea false deberemos ser nosotros quienes mostremos su resultado
Por ejemplo, sí usamos:
$form_nonce = wp_nonce_field('X_form', 'X_nonce', true, false);
Deberemos mostrarla con echo
luego.
Veamos su descripción
Description / Descripciónwp_nonce_field( int|string $action = -1, string $name = '_wpnonce', bool $referer = true, bool $display = true ): string
Vea que por defecto los parámetros serán los siguientes:
$action
– su valor por defecto será -1, esto está indicando que no habrá acción, en nuestro caso deberemos darle un valor por ejemplo "formularioA"
$name
– tendrá el valor de "_wpnonce"
$referer
– tendrá valor true
$display
– será true
Por ende, si utilizamos la función wp_nonce_field
con solo el primer parámetro hará el display en pantalla automáticamente y cuando tengamos que ver por el nonce podremos hacerlo con $_POST['_wpnonce']
Hagamos un formulario: Supongamos que tenemos que hacer un formulario para el newsletter para ello necesitaríamos el mail del usuario y si desea recibir nuestro correo periódicamente, por ejemplo: diariamente, semanalmente, mensualmente.
<html lang="es"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Formulario de Newsletter</title> <style> body { font-family: Arial, sans-serif; margin: 20px; } form { max-width: 400px; margin: auto; } label { display: block; margin-bottom: 8px; } input, select { width: 100%; padding: 10px; margin-bottom: 15px; box-sizing: border-box; } button { background-color: #4CAF50; color: white; padding: 10px 15px; border: none; border-radius: 4px; cursor: pointer; } button:hover { background-color: #45a049; } </style> </head> <body> <h2>Formulario de Newsletter</h2> <p>Suscríbete a nuestra newsletter y elige la frecuencia de envío:</p> <form action="procesar_formulario.php" method="post"> <label for="nombre">Nombre:</label> <input type="text" id="nombre" name="nombre" required> <label for="email">Correo electrónico:</label> <input type="email" id="email" name="email" required> <label for="frecuencia">Frecuencia de envío:</label> <select id="frecuencia" name="frecuencia"> <option value="diaria">Diaria</option> <option value="semanal">Semanal</option> <option value="mensual">Mensual</option> </select> <button type="submit" name="submit" value="Suscribirse" >Suscribirse</button> </form> </body> </html>
Ahora deberemos agregarle nuestra protección CSRF a nuestro formulario, esto lo podemos hacer agregando lo siguiente debajo de la etiqueta <form>:
<?php echo wp_nonce_field('formularioA'); ?>
Función wp_verify_nonce
https://blastcoding.com/proteccion-csrf-en-wordpress/#wp_verify_nonceCon esta función verificaremos que se ha utilizado un nonce seguro, el cual posee un tiempo límite.
Description / Descripciónwp_verify_nonce( string $nonce, string|int $action = -1 ): int|false
Si seguimos con el action que pusimos en nuestra función wp_nonce_field
nuestro action aquí debería ser "formularioA"
, recuerde que no hemos puesto nonce así que nuestro valor de nonce estará en $_GET['_wpnonce']
o $_POST['_wpnonce']
dependiendo del método que usemos en el formulario.
if (isset($_POST['submit'])) { // Check the nonce $nonce = $_POST['_wpnonce']; if (wp_verify_nonce($nonce, "formularioA")) { // Process the form data } else { // Handle the error } }
Vea que en este ejemplo estamos utilizando isset($_POST['submit'])
de esta manera se que he cliqueado el botón ahorrándome tiempo en verificar directamente el nonce, en definitiva ya sé que existe un $_POST['_wpnonce']
.
Luego chequeamos nuestro nonce con la función wp_verify_nonce
si esta nos devuelve true haremos el proceso del formulario, o sea validación y guardado de datos.
Función check_admin_referer
https://blastcoding.com/proteccion-csrf-en-wordpress/#check_admin_refererUtilizaremos la función check_admin_referer
si es que estamos realizando un plugin, ya que esta chequeara si nuestra página está siendo referida desde otra página admin y chequea si el nonce es correcto.
check_admin_referer( int|string $action = -1, string $query_arg = '_wpnonce' ): int|false
// chequeo el submit if (isset($_POST['submit'])) { check_admin_referer('accion', 'nonce_name'); // Si llegamos aquí, el nonce es válido, ya podemos porcesar los datos del formulario // ... }
Si el nonce es inválido, en teoría la función llamará a die() imprimiendo antes en pantalla Are you sure?