3. Seguridad del plugin

¡Felicidades, tu código funciona! Pero, ¿es seguro? ¿Cómo protegerá el plugin a tus usuarios si sus sitios son atacados? Los mejores plugins en el directorio WordPress.org protegen la información de sus usuarios.

Por favor, ten en mente que tu código puede correr en miles, quizá en millones, de sitios web, por lo que la seguridad es de la mayor importancia. Esto es especialmente importante cuando estás creando una página de ajustes para tu tema, creando y manipulando shortcodes, o guardando y renderizando datos extra asociados con un ‘post’.

Afortunadamente, existen patrones comunes que puedes seguir para asegurar la seguridad de tu código. Los hemos descompuesto en tres ideas clave:

  • Seguridad en la entrada

Cada vez que un usuario envía datos a WordPress, los datos son importados de una fuente externa, o los datos entran en WordPress, debes asegurar que es seguro de manejar. Lo puedes conseguir validando y depurando los datos.

  • Corrección en la salida

Cada vez que un título, un valor meta, o cualquier otro dato de un ‘post’ de la base de datos es mostrado al usuario, necesitamos estar seguro que está adecuadamente formateado. Esto ayuda a evitar problemas como el ‘Cross-site scripting (XSS)’, que son ataques maliciosos en los que se inyectan códigos en el sitio, generalmente esto ocurre cuando un sitio muestra información aportada por un usuario sin validarla convenientemente.

  • Confirmar credenciales

Para evitar que una persona no autorizada pueda modificar los ajustes de tu plugin o realizar acciones que no está autorizada, siempre es importante confirmar sus credenciales. WordPress ofrece dos maneras.

 

Capacitación del usuario

Cada usuario que se registra en WordPress recibe la asignación de capacidades automáticamente en función de su rol. Por ejemplo, un autor puede publish_posts y un administrador puede manage_options. Tendría sentido que tu quisieras que un autor creara contenido y un administrador gestionara el sitio. Estas capacidades se chequean en varios puntos dentro de la administación. Dependiendo de las capacidades asignadas a un rol, los menus, funcionalidades y otros aspectos de la experiencia de WordPress pueden ser añadidos o eliminados.

Cuando construyas un plugin, asegúrate prestar atención a qué roles puedes permitir realizar una acción específica. El ejemplo a continuación muestra una función auxiliar que da a los editores un link para enviar a la papelera artículos desde el front-end de su sitio:

Ahora aquí hay un ejemplo de cómo emplear la función para maneja cualquier consulta para eliminar ‘posts’:

El código anterior permite a cualquier visitante del sitio ‘clicar’ en el enlace “Delete” y enviar el artículo a la papelera. Sin embargo, tú sólo quieres que editores y roles superiores poder hacerlo. Si cualquiera puede hacerlo, tú no podrás terminar con el contenido que tú quieres.

Además, te debes asegurar que el usuario actual sólo puede hacer algo que un editor o superior puede hacer si antes está aleccionado en cualquier acción.

Cuando se genera el vínculo, debe parecer algo como esto:

Cuando se elimina, como esto:

En ambos casos, estamos confirmando que el usuario tiene las capacidades edit_others_posts antes de proceder con la acción. Si no es así, no puede hacer nada.

Entonces, ahora tu plugin es seguro, ¿correcto?. Bien, no tan rápido. Necesitas entender cómo crear “Nonces”.

 

Validación de datos

La validación de datos significa ver los datos de entrada y verificar que son correctos para su uso, antes de hacer cualquier otra cosa con ellos. “Datos de entrada” generalmente significa datos que entran desde un formulario que un usuario ha enviado, pero también pueden ser datos de cualquier fuente externa (como ‘feeds RSS’, consultas AJAX, otras llamadas de API). Algunos ejemplos sencillos de validación de datos:

  • Verificar que los campos requeridos no están en blanco.
  • Verificar que un número de teléfono solo contiene números y puntuación.
  • Verificar que el código postal introducido es real.
  • Verificar que un campo cantidad es mayor de 0.

La validación de datos se puede llevar tan lejos como sea posible. En el caso del procesado de un formulario, esto significa validar los datos antes de hacer cualquier cosa con ellos. La validación de formularios se puede realizar con JavaScript antes de que un formulario sea enviado, y entonces, con PHP, después de que se envíe. Los datos procedentes de otras fuentes serán validados con PHP.

¿Cómo se realiza la validación de datos?

Hay tres maneras:

  • Funciones PHP

La validación básica se puede realizar mediante funciones PHP pre-construidas, incluyendo las siguientes:

  • isset()empty() para verificar si una variable existe y no es nula.
  • mb_strlen()strlen() para verificar que una cadena tiene la cantidad de caracteres prevista.
  • preg_match()strpos() para verificar la existencia de ciertas cadenas dentro de otras cadenas.
  • count() para verificar cuantos elementos tiene una matriz.
  • in_array() para verificar si un elemento está dentro de una matriz.

 

  • Funciones del núcleo de WordPress

WordPress provee algunas funciones útiles que ayudan a validar diferentes tipos de datos. Algunos ejemplos:

  • is_email() verificará si una dirección de correo electrónico es válida.
  • term_exists() verifica cuando una etiqueta, categoría u otra taxonomía, existen.
  • username_exists() verifica si el nombre de usuario existe.
  • validate_file() validará si una ruta de archivo es real, aunque no si el fichero existe.

Comprueba el ‘WordPress code reference’ para más funciones como estas. Busca funciones con nombres como *_exists(), *_validate() o is_*(). No todas son funciones de validación, pero algunas pueden ser útiles.

 

  • Funciones personalizadas PHP y JavaScript

Puedes crear tus propias funciones PHP y JavaScript e incluirlas en tu tema o plugin. Cuando la escribas, la nombraras como una pregunta (is_phone, is_available, is_us_zipcode). En el final, deberás devolver un valor lógico, haciendo fácil usarlo en un condicional.

He aquí un ejemplo de función PHP que valida si un valor es un código US zip válido (código postal fuera de US):

 

Seguridad en la entrada

Cada vez que entran datos en WordPress, bien enviados a través de un formulario, bien importados de una fuente externa (feeds, llamadas API, etc), asegúrate que son seguros para manejar mediante validación e higienización.

Validar

Validar asegura que los datos recibidos desde un usuario o fuente externa son los esperados.

Por ejemplo, un campo input que pide a los usuarios un código postal:

<code><input id=”my-zipcode” type=”text” maxlength=”5″ name=”my-zipcode” /></code>

Este campo de texto permite hasta cinco caracteres de entrada sin limitaciones en el tipo de caracteres que se pueden usar. Los usuarios pueden entrar algo correcto como “11221” o algo erróneo como “eval(“. La validación asegura que sólo aceptamos códigos correctos.

Al procesar el formulario, el código debe verificar cada campo, revisando los tipos de datos y descartando cualquier cosa que no cumpla. Por ejemplo, puedes verificar que el campo anterior sólo contiene 5 dígitos numéricos:

El atributo maxlength de nuestro campo input sólo obliga al navegador, entonces tú todavía debes validar la longitud de la entrada en el servidor. Si no lo haces, un atacante puede inteligentemente enviar un formulario con un valor más largo.

La función intval() emite la entrada del usuario a un entero y zero por defecto si la entrada tiene un valor no numérico. Tú entonces revisas si el valor final es superior a cero. En tal caso, guardas un valor vacío en la base de datos. En otro caso, guardas el código postal correcto.

Este estilo de validación sigue la filosofía de la lista blanca de WordPress (permitir al usuario enviar sólo lo que tú esperas).

Otro ejemplo de la lista blanca de verificación. Digamos que vas a consultar algunos artículos de la base de datos, y quieres permitir al usuario que escoja de una lista de palabras clave. Este ejemplo a continuación, verifica una entrada de palabras clave ordenadas contra una matriz de valores permitidos, empleando la función de PHP in_array con activación de verificación de tipo estricto.

Limpiar (higienizar)

Limpiar es un enfoque más liberal de aceptar los datos del usuario. Es mejor emplear este método cuando hay un rango de entradas aceptables.

Por ejemplo, un campo de entrada que consulta a los usuarios por un título:

<code><input id=”title” type=”text” name=”title” /></code>

Puedes limpiar los datos con la función sanitize_text_field():

Encubiertamente, sanitize_text_field comprueba:

  • valida código UTF-8 no válido
  • Convierte caracteres en cadena
  • Elimina todas las etiquetas
  • Elimina roturas de línea, tabuladores y espacios en blanco adicionales.
  • Elimina código octal.

La clase sanitize_*() de funciones auxiliares:

  • sanitize_email()
  • sanitize_file_name()
  • sanitize_html_class()
  • sanitize_key()
  • sanitize_meta()
  • sanitize_mime_type()
  • sanitize_option()
  • sanitize_sql_orderby()
  • sanitize_text_field()
  • sanitize_title()
  • sanitize_title_for_query()
  • sanitize_title_with_dashes()
  • sanitize_user()
  • esc_url_raw()
  • wp_filter_post_kses()
  • wp_filter_nohtml_kses()

Conclusión

Cada vez que estás aceptando datos potencialmente inseguros, es importante validarlos o limpiarlos. Validación es confirmar que los datos son como tú esperabas. Limpiar es una forma más liberal de limpiarlos.

 

Seguridad en la salida

Siempre que se muestran datos, te debes asegurar que están debidamente escapados justo antes de ser mostrados. Escapar significa pelar o eliminar datos no deseados, tales como HTML mal montado o etiquetas script.

Escapando

Escapar ayuda a asegurar tus datos antes de mostrarlos al usuario final. WordPress tiene unas pocas funciones de ayuda que puedes emplear para la mayor parte de lo que comúnmente necesitas hacer:

  • esc_html()

Emplea esta función siempre que un elemento HTML encierra una sección de datos mostrados.

<code><h4><?php echo esc_html( $title ); ?></h4></code>

  • esc_url()

Emplea esta función en todas las URLs, incluyendo los aributos srchref de un elemento HTML.

<code><img src=”<?php echo esc_url( $great_user_picture_url ); ?>” /></code>

  • esc_js()

Emplea esta función para JavaScript.

<code><a href=”#” onclick=”<?php echo esc_js( $custom_js ); ?>”>Click me</a></code>

  • esc_attr()

Emplea esta función en cualquier cosa que es mostrada dentro de un atributo de un elemento HTML.

<code><ul class=”<?php esc_attr( $list_class ); ?>”></code>

NOTA: Muchas de las funciones WordPress preparan adecuadamente los datos para la salida por pantalla, por lo que no tienes que escapar los datos otra vez. Por ejemplo, puedes emplear con tranquilidad the_title() sin escapar.

<code><h4><?php the_title(); ?></h4></code>

 

Escapar con localización

Antes que emplear echo para mostrar datos, es común preferir las funciones de localización de WordPress, tales como _e()__().

En este caso, hay funciones de ayuda adicionales que combinan localización y escape. Estas son:

  • esc_html__()
  • esc_html_e()
  • esc_html_x()
  • esc_attr__()
  • esc_attr_e()
  • esc_attr_x()

Estas funciones simplemente mezclan una función de localización dentro de una función de escape:

 

Escapar con HTML permitido

En el caso de que tu tipo de salida no haga juego con ninguna de las funciones de escape existentes, wp_kses() escapa especificándole qué etiquetas HTML están permitidas.

Esta función asegura que sólo los elementos atributos, valores de atributos HTML especificados pasarán en tu salida, y normaliza las entidades HTML.

wp_kses_post() escapará tu salida de la misma manera, excepto el HTML permitido predefinido para utilizar los mismos elementos como contenido del post.

<code>echo wp_kses_post( $post_content );</code>

 

Conclusión

Siempre que estás mostrando datos, asegúrate escaparlos adecuadamente. Ello ayuda problemas como el ‘cross-site scripting’.

 

Nonces

Nonces son números generados, empleados para verificar el origen y la intención de solicitud, para propósitos de seguridad. Cada nonce sólo puede ser usado una vez e incluye la capacidad de chequear para confirmar el origen. Piensa en ello como un símbolo secreto para asegurar que una acción es válida.

En WordPress, la capacidad de chequeo asegura que sólo los usuarios que tienen permisos para eliminar un post son capaces de borrarlo. ¿Pero qué pasa si alguien engaña clicando el botón? Tienes la capacidad necesaria, pues puedes inconscientemente borrar el post. Nonces se pueden emplear para comprobar que el usuario actual intenta realizar la acción seleccionada.

Cuando generas el link, emplea wp_create_nonce() para añadirle un nonce.

El argumento pasado a la función asegura que el nonce creado es único para la acción en particular.

Entonces, cuando estas procesando una consulta para eliminar un link, puedes verificar que el nonce es el que esperas que sea:

 

Conclusión

Cuando realizas cualquier tipo de operación de transformación de datos, por ejemplo, guardar un formulario de ajustes o eliminar un artículo, asegúrate siempre que el usuario es quien dice ser y tiene los permisos necesarios para ejecutar la acción. Con ambas premisas significa que los datos sólo se modifican cuando el usuario es el adecuado.

Deja un comentario

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