Plugin WordPress. Seguridad en el código

En mi corta experiencia en la programación de un plugin WordPress, un tema que había obviado era la seguridad del código. Al solicitar a wordpress.org el permiso para subir un nuevo plugin al repositorio oficial, me fue denegado alegando falta de seguridad, aunque, afortunadamente, me dieron las pautas para implementarla. Finalmente, tras hacerlo, han aceptado mi solicitud.

Vamos a ver en este artículo cómo hacerlo.

Seguridad en un plugin WordPress. Conceptos básicos

En un plugin WordPress se pueden producir problemas de seguridad en diversos puntos:

  • Llamadas POST/GET/REQUEST.
  • Escritura de datos en la base de datos.
  • Salida de datos por pantalla.

En todos estos casos, debemos observar cuáles de estas operaciones debemos efectuar previamente con los datos:

  • Higienizar (sanitize). Al higienizar un dato antes de guardarlo en la base de datos, reduces la posibilidad de vulnerabilidades XSS (Cross-site scripting, Secuencias de órdenes en sitios cruzados). Con esta vulnerabilidad, permites a terceras personas inyectar código malicioso tipo JavaScript o similar.
  • Validar (validate). Conjuntamente con la higienización de nuestros datos, es importante validarlos antes de operar con ellos, vigilando los rangos y características necesarias de los mismos, para evitar respuestas incorrectas por los datos introducidos por el usuario.
  • Escapar (escape). Finalmente, resulta conveniente la última revisión de nuestros datos justo antes de que sean mostrados por pantalla, adecuándolos convenientemente, en función de su cometido.

Vamos a ver ahora cómo implementar la seguridad en un plugin WordPress.

 

Cómo implementar la seguridad en un plugin WordPress

Para implementar la seguridad en un plugin WordPress, vamos a utilizar el siguiente artículo de mi querido Codex.

 

Higienizar (sanitize)

Cuando recibimos un dato mediante el sistema POST/GET/REQUEST, debemos higienizarlo, es decir, limpiarlo de cualquier posible código malicioso.

Para ello, disponemos de diversas funciones del núcleo de WordPress ya implementadas, que cumplen con dicho objetivo y cuyo listado completo encontraréis en el artículo del Codex arriba referenciado.

Un caso sencillo es el de la higienización de un simple campo de texto de un formulario. Para ello, emplearemos la función sanitize_text_field( $cadena ). Esta función realiza los siguientes procesos con la cadena de texto:

  • Chequea código UTF-8 no válido.
  • Convierte caracteres ‘<‘ simples a entidades.
  • Tira todas las etiquetas.
  • Elimina todos los retornos, tabulaciones y espacios innecesarios.
  • Tira los octetos.

 

Validar (validate)

Una vez recibimos los datos insertados por el usuario en el campo del formulario, comprobaremos, principalmente, dos factores:

  • Que el tipo de dato sea el que necesita el código para las operaciones que realizará después con él.
  • Que el dato se encuentra dentro del rango de datos admisibles.

Además, puede haber otras comprobaciones a realizar, según el código que cada uno haya creado.

Al contrario que en las otras 2 operaciones de seguridad, en este caso el código de validación no dispone de funciones propias del núcleo de WordPress.

 

Escapar (escape)

Finalmente, y en el extremo opuesto del flujo de operaciones del plugin WordPress, es decir, en la salida de datos, debemos escaparlos correctamente. Sería algo así como filtrar los datos para que su salida por pantalla no pueda ocasionar problemas al usuario.

El núcleo de WordPress nos provee con diferentes funciones de escape, a utilizar en función de el lugar o del tipo de dato que vamos a mostrar:

  • esc_html() para cualquier elemento HTML que vayamos a mostrar.
  • esc_url() para utilizar con URLs.
  • esc_js() para JavaScript dentro de un elemento.
  • esc_attr() para cualquier atributo de un elemento HTML.
  • esc_textarea() para mostrar texto extraído de un elemento textarea.

 

Mi caso como ejemplo práctico

El pasado miércoles, 28 de diciembre, ante mi solicitud para la subida de mi nuevo plugin STM WooCommerce Gallery, variante para WooCommerce del plugin STM Gallery, recibo respuesta en la que me indican los problemas de seguridad de mi plugin.

Además, lo cual me permite atestiguar la profesionalidad de los que allí trabajan, me envían dos trozos de mi propio código, como ejemplo de los problemas que debo resolver.

y

El primer trozo de código pertenece a la función de guardado de los datos introducidos en la página de edición de las composiciones que crea mi plugin.

El segundo trozo es la recepción a través de AJAX de unos parámetros necesarios para la creación de las composiciones.

 

Cómo resuelvo esto

Debo reconocer que, en un primer momento, esta respuesta supuso un mazazo moral para mi. Todo el tiempo que inviertes en el desarrollo de un plugin, todo el esfuerzo y toda la ilusión, al traste en el último momento (sensación de botella vacía).

Sin embargo, en el mismo momento, pienso que es un nuevo reto y, sobretodo, una oportunidad para mejorar como desarrollador WordPress.

Por tanto, libreta en mano, vamos a ver el alcance del problema y cómo lo solucionamos:

 

Escapando la salida de los datos

Primero busqué todas las funciones echo que había en mi plugin. Como se aprecia en la derecha de la imagen, eran 63 veces.

De ellas, 3 casos se podían eliminar, ya que aparecían en una instrucción JavaScript console.log que utilizo para depurar código a través de mensajes en la consola del navegador.

De los 60 restantes, 49 se correspondían a la internacionalización mediante __(). En un primer momento pensé que, al ser las cadenas que yo creo para mostrar en pantalla, no sería necesario escaparlas. Pero, pensando un poco más, yo internacionalizo mis plugins para que la gente pueda traducirlos. Por tanto, algún traductor malvado podría crear código malicioso en un determinado idioma. La solución fue cambiar __() por esc_html__(). Así todo resuelto.

Me quedaban 11, 10 de los cuales solucioné incluyendo simplemente esc_html a la variable que quería mostrar por pantalla.

Finalmente, la línea 552 devuelve el resultado de las dos funciones finales del algoritmo AJAX de mi plugin: una crea el código HTML de las composiciones, y la otra crea el estilo CSS deseado.

Probé directamente con esc_html en la misma línea, pero por pantalla se me mostraba texto en lugar de las composiciones. Por tanto, acudí a las funciones a escapar los diferentes datos uno por uno. Un ratito de faena, y todo quedó correcto.

 

Higienizando y validando los datos de entrada

Como se puede ver en la parte izquierda superior de la imagen, los datos se reciben en dos trozos de código muy localizados: Primero, entre las líneas 417 y 429; luego, entre las líneas 536, 537, 538.

La función

Primero, para no generar mucho código intermedio de higienización y validación, opté por crear una función adicional a mi plugin que higienizara el valor y, en función del campo que se tratara, lo validara adecuadamente.

La implementé en el final del código del plugin, y ya sólo me faltaba llamarla.

Las llamadas

Primero, en el salvado de ajustes de las composiciones en la base de datos:

Finalmente, en la recepción de los parámetros de la llamada AJAX.

 

Conclusiones

  1. Ante todo, personalmente añadiré a mi checklist de creación de plugins el apartado de seguridad. Lo mismo para los themes.
  2. Recordad dónde debéis hacer hincapié en este tema: Llamadas POST/GET/REQUEST, escritura de datos en la base de datos y salida de datos por pantalla.
  3. Además, obviamente, realizaré el mismo arreglo en mi anterior plugin, STM Gallery, mediante una nueva versión.

 

Finalmente, el plugin ha sido aceptado, por lo que lo publicaré entre los pañales de primera postura del nuevo año. Mientras tanto, quien lo desee, está a su disposición en GitHub, en https://github.com/sergioTOCAMORENO/STM-WooCommerce-Gallery.

 

Sed muy felices en este próximo cambio de año.

3 opiniones en “Plugin WordPress. Seguridad en el código”

    1. Muchas gracias, Miguel.

      Observo que ya has empezado a hacer la lista de propósitos para el nuevo año, jeje.

      Por cierto, te quiero nombrar en un post. ¿Me das permiso?

      Saludos, un abrazo, y feliz entrada de año.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *