Blog de programación, errores, soluciones

Chose Language:
Author: Admin/Publisher |finished | checked

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_field

Esta 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ón
wp_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>
newsletter form

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_nonce

Con esta función verificaremos que se ha utilizado un nonce seguro, el cual posee un tiempo límite.

Description / Descripción
wp_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'].

Puedes ver mas sobre isset en : https://blastcoding.com/php-isset/

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_referer

Utilizaremos 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.

Description / Descripción
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?

Category: wordpress
Something wrong? If you found an error or mistake in the content you can contact me on Twitter | @luisg2249_luis.
Last 4 post in same category