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?

