Seguridad front-end de WordPress: CSRF y Nonces | Programar Plus

En nuestro último artículo, cubrimos Cross-Site Scripting (XSS) y las funciones que proporciona WordPress para prevenir ataques XSS. Hoy, veremos otra preocupación de seguridad para los desarrolladores front-end: la falsificación de solicitudes entre sitios (CSRF).

Para que no crea que esto de la seguridad no es importante, recientemente se encontró una vulnerabilidad importante en el complemento WP SEO, que está instalado en más de 1,000,000 de sitios de WordPress y que permitió a los piratas informáticos manipular la base de datos de WordPress usando CSRF. (El complemento se solucionó rápidamente, pero puede ver lo aterrador que puede ser esto).

Nonces y falsificación de solicitudes entre sitios

En pocas palabras, CSRF es cuando los malos intentan engañar a los usuarios (generalmente alguien con acceso al panel de control de WordPress) para que hagan algo que no tenían la intención de hacer. Un ejemplo simple puede ayudar a ilustrar:

Suponga que está creando un complemento de WordPress para permitir que los usuarios registrados envíen sus imágenes. En la parte frontal del sitio, su complemento podría generar un formulario como este:

<?php if ( is_user_logged_in() ) : ?>
  <form action="/submit-picture/" method="get">
    <input type="text" name="picture_url">
    <input type="submit">
  </form>
<?php endif; ?>

En el back-end, usted maneja los envíos de formularios de imágenes:

if ( is_user_logged_in() && isset( $_REQUEST['picture_url'] ) ) {
  // Save the picture here
}

Ahora, supongamos que un hacker quiere enviar una imagen falsa. El pirata informático no tiene un nombre de usuario o contraseña, por lo que no puede hacer nada, ¿verdad?

No exactamente. Para secuestrar una de las cuentas de sus usuarios para enviar una imagen falsa, el pirata informático podría intentar que un usuario que haya iniciado sesión haga clic en un enlace que se ve así:

http://your-site.com/submit-picture/?picture_url=fake-picture.jpg

Si un usuario que ha iniciado sesión hace clic en ese enlace, ¿qué impediría que se envíe la imagen? Lo adivinaste: Nada. El hacker gana.

Eso es porque no hicimos nada para verificar el usuario intención para enviar una imagen. La “F” en CSRF significa falsificación: el pirata informático ha falsificado (simulado) una solicitud en nombre del usuario, algo así como falsificado la firma de tu mamá en las notas de enfermedad en la escuela primaria.

Cómo prevenir CSRF

Podemos detener los ataques CSRF mediante el uso de algunas funciones útiles integradas en WordPress. Para evitar que una solicitud sea “falsificada” con éxito, WordPress usa nonces (números usados ​​una vez) para validar que la solicitud fue realmente realizada por el usuario actual.

El proceso básico se ve así:

  1. Se genera un nonce.
  2. Ese nonce se envía con el formulario.
  3. En el back-end, se comprueba la validez del nonce. Si es válido, la acción continúa. Si no es válido, todo se detiene: ¡probablemente la solicitud fue falsificada!

Agreguemos un Nonce

En la parte delantera, supongamos que queremos agregar un nonce al envío de un formulario. Haremos esto con la función de conveniencia wp_nonce_field:

<form action="/submit-picture/" method="get">
  <input type="text" name="picture_url">
  <input type="submit">
  <?php wp_nonce_field( 'submit_picture' ); ?>
</form>

Fácil, ¿verdad? Ahora, cuando procesamos este formulario en el back-end, solo necesitamos usar algunas funciones integradas de WordPress para verificar que el nonce sea válido:

// By default, we can find the nonce in the "_wpnonce" request parameter.
$nonce = $_REQUEST['_wpnonce'];
if ( ! wp_verify_nonce( $nonce, 'submit_picture' ) ) {
  exit; // Get out of here, the nonce is rotten!
}

// Now we can process the submission
if ( is_user_logged_in() && isset( $_REQUEST['picture_url'] ) ) {
  // Save the picture here
}

Debido a que el nonce es desconocido para el pirata informático, no puede crear un enlace falso que cause daño. Cualquier intento malicioso será aplastado en el wp_verify_nonce cheque. Hemos detenido al hacker, ¿verdad? Para muchos casos, sí. Hemos hecho que sea mucho más difícil para un hacker falsificar una solicitud.

Los nonces son específicos del usuario

Pero ¿y si un mal usuario registrado de su sitio quería enviar una imagen falsa para otro usuario? ¿No podría el mal usuario simplemente mirar la fuente HTML del sitio, encontrar el campo nonce y agregarlo a su URL “malvada” de esa manera?

http://your-site.com/submit-picture/?picture_url=fake-picture.jpg&_wpnonce=NONCEVALUE

Por suerte, no funcionará. Los nonces de WordPress son únicos para la sesión de un usuario, por lo que un hacker no podría sustituir su propio nonce por otro usuario.

Felicitación a Mark Allen en los comentarios por señalar los nonces únicos de la sesión.

Pruebe estas funciones de Nonce

WordPress está lleno de funciones convenientes para facilitar la generación de nonces (y la prevención de CSRF). Aquí hay algunos que pueden resultarle útiles para diferentes situaciones:

Función: wp_verify_nonce

Que hace: Valida que el valor nonce fue generado legítimamente por WordPress.

No importa cómo genere su nonce, debe verificarse en el back-end con wp_verify_nonce

Al igual que los ejemplos anteriores, utilice wp_verify_nonce para verificar la intención de un usuario:

$submitted_value = $_REQUEST['_wpnonce'];

if ( wp_verify_nonce( $submitted_value, 'your_action_name' ) ) {
  // nonce was valid...
}

Entrada del códice para wp_verify_nonce

Función: wp_nonce_field

Que hace: Imprime un oculto <input> etiqueta que contiene un valor nonce.

Se utiliza cuando se está construyendo un <form> que necesita ser protegido de CSRF (que es casi todos <form>).

Al igual que en los ejemplos anteriores, wp_nonce_field es una función conveniente para hacernos la vida más fácil creando formularios HTML:

<form>
<!-- Other form fields go here -->
<?php wp_nonce_field( 'your_action_name' ); ?>
</form>

Entrada del códice para wp_nonce_field

Función: wp_nonce_url

Que hace: Devuelve una URL con un valor nonce adjunto.

Se usa cuando está creando una URL que necesita un campo nonce agregado como parámetro de cadena de consulta. Más útil cuando se realizan solicitudes GET que necesitan validación CSRF.

Aquí hay un ejemplo de wp_nonce_url donde necesitamos validar que un usuario pretendía hacer clic en un enlace:

<?php
  $action_url = wp_nonce_url( '/change-color/?color=blue', 'change_color' );
  // $action_url is now "/change-color/?color=blue&_wpnonce=GENERATED_VALUE"
?>
<a href="https://css-tricks.com/wordpress-front-end-security-csrf-and-nonces/<?php echo esc_url( $action_url ); ?>">Change to blue</a>

Entrada del códice para wp_nonce_url

Función: wp_create_nonce

Que hace: Genera un valor nonce.

Se usa cuando necesita un valor nonce que no se ajusta a una de las funciones de conveniencia anteriores.

Aquí está wp_create_nonce se usa para generar un valor nonce para regresar en formato JSON (útil para regresar en solicitudes AJAX):

<?php
  $nonce_value = wp_create_nonce( 'your_action_name' );

  return json_encode( array( 'nonce' => $nonce_value ) );
?>

Entrada del códice para wp_create_nonce

Función: check_ajax_referer

Que hace: Comprueba un nonce enviado usando wp_verify_nonce, y si la validación falla, detiene la ejecución.

check_ajax_referer es otra función conveniente principalmente para uso en solicitudes AJAX. Puede usarlo para omitir hacer el wp_verify_nonce compruébalo tú mismo:

<?php
  // Forged requests won't get past this line:
  check_ajax_referer( 'your_action_name' );

  // Do your action here
?>

Entrada del códice para check_ajax_referer

¡Nonces para todo!

Las vulnerabilidades de CSRF van desde inofensivas (por ejemplo, envíos de encuestas) hasta extremadamente peligroso (por ejemplo, modificar contraseñas o permisos).

Independientemente de la gravedad, debe usar nonces para evitar CSRF cada vez que un usuario realiza una acción en WordPress. Porque… ¿por qué no lo harías? No desea que los piratas informáticos falsifiquen solicitudes en su sitio, y WordPress le brinda las herramientas para detenerlos.

¡Use nonces, detenga la falsificación y frustre a los piratas informáticos!

(Visited 16 times, 1 visits today)