#WCMadrid 2018: Codename Servehappy y Project Tide

WordPress y PHP siempre pueden ir en la misma frase, y es que PHP es el corazón del gestor de contenidos más importante de Internet. Es por eso que dos de los proyectos que se han gestado en estos últimos meses toman relevancia cuando se acerca la versión 5.0 de WordPress.

Ahora mismo hay 4 versiones / ramas de PHP activas… pero ¿las soporta WordPress?

  • 5.6.34: no soportada
  • 7.0.28: soportada, no recomendada
  • 7.1.15: soportada, no recomendada
  • 7.2.3: recomendada

Por esto se ha creado el proyecto Servehappy, con la idea de que tu instalación de WordPress detecte qué versión tienes y te ayude a actualizar. Incluso, en algunos casos le propio WordPress Danger es capaz de decirte si tus plugins y themes son compatibles.

Pero quizá lo más interesante es el proyecto Tide, un sistema que analiza la calidad de plugins y themes y que te dice, además de si es compatible con tu versión de PHP, si el desarrollo está bien hecho y cumple unos mínimos estándar.

Si quieres, solo has de descargarte la presentación, disponible bajo licencia EUPL 1.2.

La comunidad WordPress española en Meetup

Si quieres aprender sobre WordPress, además de lo que puedas encontrar por Internet, lo más recomendable es acercarte a alguna de las comunidades locales que hay alrededor de toda España (y si no la hay, ¿has pensado en crearla?). Esta es una recopilación de las distintas Meetup que hay.

Andalucía

Aragón

Asturias

Baleares

Canarias

Cantabria

Castilla La Mancha

Castilla y León

Cataluña

Extremadura

Galicia

Madrid

Murcia

Navarra

País Vasco

Valencia

Última actualización: 2018-02-05
¿Crees que falta alguna? No dudes en escribirme un correo [javier-arroba-casares.org] que la añadiré.

La comunidad WordPress española en Twitter

Me atrevería a decir que España tiene una de las comunidades WordPress más importantes del mundo, y así se refleja en muchas ocasiones por la cantidad de Meetups o de WordCamp que se realizan. Por eso me he parado a hacer una recopilación de cuentas de Twitter de las distintas comunidades que hay.

WordCamp

Andalucía

Canarias

Cataluña

Madrid

País Vasco

WordPress

Andalucía

Aragón

Asturias

Baleares

Canarias

Cantabria

Castilla y León

Cataluña

Extremadura

Galicia

Madrid

Murcia

Navarra

País Vasco

Valencia

WooCommerce

Madrid

Otros

Oficiales

Última actualización: 2018-02-05
¿Crees que falta alguna? No dudes en escribirme un correo [javier-arroba-casares.org] que la añadiré.

Continuando la evolución de WPdanger

Cuanto más tiempo le dedico a la seguridad de los WordPress, más me doy cuenta de la dejadez de muchos de sus usuarios. Y es que cuando comencé con WPdanger todo venía un poco del mal trago que tuve que pasar con un proyecto que me toca de cerca y que prácticamente se había dejado. Y eso que era un WooCommerce.

Según ha pasado el tiempo y he podido ver análisis de cientos de sitios, voy viendo que sí, que cada vez más usuarios mantienen al día sus sitios pero que, aún siendo la recomendación más dada -mantén al día tu WordPress, los plugins y plantillas- parece que no vemos que no es suficiente.

Esto que he ido viendo en algunas WordCamp como la de Santander o la de Zaragoza me ha hecho lanzar WPdanger Code, el sitio en el que publico algunos bloques de código y artículos con recomendaciones.

Pero, aún así, no es suficiente. Es cierto que estar al día es muy acertado pero ¿por qué dejar ver qué tiene tu sitio, qué plugins utilizas? Y ahí es donde me entran las dudas… no sé si es que los que usamos WordPress no tenemos claro que hay que proteger nuestro hosting (y algunas configuraciones propias de WordPress) o es que simplemente tenemos ya la idea en la cabeza de que “como WordPress es seguro, estar con todo actualizado es suficiente”.

La primera versión de WPdanger era bastante sencilla… simplemente hacía el análisis, te mostraba lo que tenías, y poco más. Poco después añadí ciertas funcionalidades extras como la integración básica del “Project Tide” de WordPress (para analizar la calidad del código de plugins y themes, y que creo que va a sacar las vergüenzas a muchos desarrolladores), el análisis de un antivirus, el sitio con documentación y códigos para aumentar la prevención… aún así, sigo viendo de forma recurrente algunos sitios que van haciendo análisis y no acabo de ver una evolución en cuanto a protección. Lo ideal es que WPdanger te dijera que “no sabe nada de tu sitio”.

Estos últimos días he dedicado bastante tiempo a montar un VPS sin nada, ponerle un WordPress con una decena de plantillas destacadas y una veintena de plugins habituales y hacer un primer análisis. En aquel momento (aunque estaba todo al día) me detectaba lo que no está escrito. Haciendo tunning del servidor, comenzando a ocultar algunos elementos desde el exterior (desde la configuración del nginx, y seguramente también se podría hacer desde los .htaccess) fui dejando de ver la lista de plugins, la lista de plantillas (exceptuando la que tenía puesta), y comencé solo a ver elementos “detectados de forma agresiva”. Eso es buena señal, si el sistema solo detecta elementos haciendo “ataques” contra el sitio y no de forma pasiva, quiere decir que alguien que use herramientas sencillas y necesite poco tiempo para detectar ataques, lo va a tener complejo porque tendrá que aplicar muchos más recursos.

Tras la presentación en la meetup de Barcelona y el taller de seguridad en Zaragoza he tomado la decisión de comenzar a ofrecer servicios de prevención para aquellos que usan WordPress, creo que a unos precios asumibles para alguien mediano o que ha sufrido algún tipo de ataque. Para bien o para mal, aunque tengo medio paquetizado todo, lo más probable es que tengan que ser servicios personalizados, ya que en general cada WordPress es un mundo… aún así, me he prometido intentar mantener el servicio lo más estándar posible.

Otra cosa que me he encontrado bastante últimamente es el asunto de los “plugins de seguridad”. Es curioso porque los plugins como Sucuri o Wordfence son de los plugins que tienen más incidencias y vulnerabilidades documentadas… lo que hace que un sitio en general seguro pueda convertirse en inseguro por poner en marcha estos plugins… ¿realmente es necesario tener un sistema como ese? Yo suelo ser partidario de eliminar puntos de fallida, y soy muy dado a tener un Firewall en modo WAF fuera del propio sistema, lo mismo que tener el correo en un sitio, las DNS en otro, el hosting en uno distinto…

Al final, y en resumen, la cuestión es… tienes un WordPress y ¿vas a dejar la seguridad de tu sitio en manos de la Comunidad o de tu Hosting, o vas a ser un poco proactivo en intentar promover sistemas de seguridad activa? Obviamente la comunidad aporta muchísimo, pero requiere que pongas de tu parte (no va a venir alguien que contribuye a actualizar tu sitio), y lo mismo tu hosting, que puede poner medidas de seguridad, pero va a tener que dejar el sistema lo más estándar posible y no va a poner medidas extremas que puedan hacer incompatible tu configuración de WordPress.

Al fin y al cabo, como en todo, si buscas seguridad, privacidad y todo lo demás, has de comenzar por ti mismo (o dejarte que te asesoren bien).

Seguridad WordPress

Cada vez más personas utilizan WordPress como gestor de contenidos, ya sea un blog, un sitio web corporativo, o directamente foros, o un e-commerce. Este hecho de que cada vez más personas decidan utilizar WordPress hace que se convierta en un punto de inicio de ataques contra usuarios y sistemas.

Si eres de los que utiliza WordPress, para empezar, tranquilo: WordPress es seguro (las personas no tanto).

Aquí te dejo la presentación de la meetup de WordPress Barcelona en la que hablo de seguridad, presento WPdanger, hablo del próximo Proyecto Tide de WordPress…

Descárgate la presentación en formato PDF (987 KB).

WP-CLI para mantenimiento y seguridad

Si utilizas WordPress y tienes la posibilidad de gestionar el acceso por Shell, sin duda has de tener disponible WP-CLI. Y si utilizas WP-CLI entonces ya sabes que existen una decena de comandos que te facilitan la vida.

En general tengo puesto en mi agenda hacer al menos una revisión semanal de todos los WordPress que tengo, y eso incluye cierto mantenimiento y, de paso, darle una ojeada a los distintos elementos para que, de un vistazo, no se haya colado nada que no tenga que estar…

Esta es una pequeña lista de comandos que uso en este orden para revisar, verificar y actualizar el sistema.

$ reviso la versión de la instalación de WP-CLI
wp cli version
$ compruebo si hay actualizaciones disponibles de WP-CLI
wp cli check-update
$ actualizo WP-CLI a su última versión
wp cli update

$ entro en la carpeta de la instalación que quiero analizar
cd /carpeta/de/instalacion/wordpress/

$ verifico que no haya nada "raro" instalado en el core
wp core verify-checksums
$ listo la configuración del wp-config
wp config get
$ listo la lista de usuarios
wp user list

$ reviso la versión del WordPress
wp core version
$ compruebo si hay una nueva versión del WordPress
wp core check-update
$ actualizo a la última versión del WordPress
wp core update --path="/carpeta/de/instalacion/wordpress/"
$ verifico que no haya nada "raro" instalado en el core
wp core verify-checksums

$ hago una lista de todos los plugins instalados
wp plugin list --path="/carpeta/de/instalacion/wordpress/"
$ listo todos los plugins que tienen actualizaciones
wp plugin update --dry-run --all --path="/carpeta/de/instalacion/wordpress/"
$ actualizo todos los plugins que tienen actualizaciones
wp plugin update --all --path="/carpeta/de/instalacion/wordpress/"

$ hago una lista de todas las plantillas instaladas
wp theme list --path="/carpeta/de/instalacion/wordpress/"
$ listo todas las plantillas que tienen actualizaciones
wp theme update --dry-run --all --path="/carpeta/de/instalacion/wordpress/"
$ actualizo todas las plantillas que tienen actualizaciones
wp theme update --all --path="/carpeta/de/instalacion/wordpress/"

$ hago una lista de todos los idiomas instalados
wp language core list --status=installed
$ listo todos los idiomas que tienen actualizaciones
wp language core update --dry-run --path="/carpeta/de/instalacion/wordpress/"
$ actualizo todos los idiomas que tienen actualizaciones
wp language core update --path="/carpeta/de/instalacion/wordpress/"

$ elimino todos los transients caducados
wp transient delete --expired
$ compruebo el prefijo del WordPress
wp db prefix
$ verifico el tamaño de la base de datos del WordPress
wp db size
$ optimizo la base de datos del WordPress
wp db optimize
$ verifico el tamaño de la base de datos del WordPress
wp db size

Obviamente este listado de comandos tiene algunos “inútiles” pero que son válidos para comprobar por enésima vez que todo es correcto y que nada se descuadra de lo que ha de ser. De la misma forma hay varios comandos que revisa y re compruebas elementos que no son necesarios comprobar. Pero aún así, con este listado, poco a poco, salen las cosas bien.

WordPress SEO: ¿Yoast o más sencillo?

En muchas ocasiones cuando instalamos un WordPress vamos con nuestra lista predefinida de plugins, y habitualmente incorporamos uno de SEO. Estos plugins de SEO en realidad hacen poco, ya que es cierto que WordPress no permite de serie gestionar cómo queremos los títulos, pero él es capaz de generar automáticamente el meta-description si se hace bien.

Es por esto que mucha gente utiliza Yoast como plugin de SEO, que además de llevar muchas herramientas que te dicen cómo escribir (algo que nunca he usado ni usaría), te corrigen (en cierta manera) el formato de título y snippet que se muestra en los resultados de búsqueda.

Hace poco me puse a buscar una solución que fuera extremadamente simple para el tema de eso: título, descripción y palabras clave. Estos tres viejos elementos son en el fondo lo único que necesitaba, el resto ya lo hace bien la plantilla. Y acabé encontrando un plugin que no está en el repositorio oficial pero que está gestionado como tal: WP SEO: A simple, straightforward SEO plugin for WordPress. Just the facts, Jack. Para aquellos que quieran, descarga la versión 0.13.0.

Este plugin lo que hace es añadir estos campos:

Y hace simplemente eso… aunque se pueden usar los distintos códigos de sustitución:

#archive_date#
#author#
#categories#
#date_modified#
#date_published#
#excerpt#
#post_type_plural_name#
#post_type_singular_name#
#search_term#
#site_description#
#site_name#
#tags#
#term_description#
#term_name#
#thumbnail_url#
#title#

Con estos códigos te puedes hacer la configuración personalizada para todos los tipos de página que tengas en tu sitio:

En la última opción, que te permite crear tus propios “metas”, podrías por ejemplo configurar uno para Google Search Console, de forma que el nombre sea google-site-verification y el content, el identificador que Google proporciona.

Lo siguiente es… si hasta ahora he estado utilizando Yoast ¿puedo migrar los datos de Yoast a este sistema? La respuesta es sí, se puede hacer, aunque no tengo ningún plugin ni nada parecido. Aún así, con 2 consultas SQL se hace muy rápido:

UPDATE wp_postmeta SET meta_key = '_meta_title' WHERE meta_key = '_yoast_wpseo_title';
UPDATE wp_postmeta SET meta_key = '_meta_description' WHERE meta_key = '_yoast_wpseo_metadesc';

Y si quieres hacer limpieza una vez desinstalado Yoast, puedes borrar “los restos”:

DELETE FROM wp_postmeta WHERE meta_key LIKE '_yoast%';

A partir de aquí tendrás una forma sencilla de añadir el título, descripción y keyworks que quieras sin necesidad de instalar un plugin pesado como son generalmente los de SEO.

Mejora la página de mantenimiento de WordPress

Cuando actualizamos el núcleo de WordPress, sus plantillas o los plugins, en ese fragmento de tiempo pequeño, suele aparecer un breve mensaje de texto en cualquier pantalla de navegación en la que nos encontramos. Esa pantalla suele ser una pantalla fría, blanca con el mensaje de texto Briefly unavailable for scheduled maintenance. Check back in a minute. Sin duda no es la pantalla más bonita que podemos mostrarle a nuestros usuarios, es útil, pero no tiene gracia.

El mantenimiento de WordPress se gestiona por la creación de un fichero en la carpeta raíz (donde está el index.php principal) llamado .maintenance. El hecho de que exista este fichero con un pequeño codigo hace que todo el sitio quede bloqueado hasta que acaben de actualizarse todos los complementos.

¿Te gustaría darle un formato un poco más elegante a la página? Se puede hacer, creando un fichero en PHP que haga lo mismo que hace el sistema por defecto, pero con cierto contenido. Para ello deberás incluir el fichero maintenance.php dentro de la carpeta /wp-content/.

Ese fichero ha de tener una cabecera que devuelva un código 503 (conforme la página no está accesible temporalmente) y el tiempo en el que se debe volver a revisar. Como habitualmente las actualizaciones de WordPress son rápidas, pondremos que el reintento se haga en 1 minuto.

<?php
wp_load_translations_early();
$protocol = wp_get_server_protocol();
header($protocol.' 503 Service Unavailable', true, 503);
header('Retry-After: 60');
header('Content-Type: text/html; charset=utf-8');
?>

Teniendo esto en cuenta, podemos crear diseños que tengan al menos alguna animación:

<?php
wp_load_translations_early();
$protocol = wp_get_server_protocol();
header($protocol.' 503 Service Unavailable', true, 503);
header('Retry-After: 60');
header('Content-Type: text/html; charset=utf-8');
?>
<!DOCTYPE html>
<html>
<head>
  <title><?php _e('Maintenance'); ?></title>
  <style>.container{width:200px;height:100px;padding-top:100px;margin:0 auto}.ball{width:10px;height:10px;margin:10px auto;border-radius:50px}.ball:nth-child(1){background:#ff005d;-webkit-animation:right 1s infinite ease-in-out;-moz-animation:right 1s infinite ease-in-out;animation:right 1s infinite ease-in-out}.ball:nth-child(2){background:#35ff99;-webkit-animation:left 1.1s infinite ease-in-out;-moz-animation:left 1.1s infinite ease-in-out;animation:left 1.1s infinite ease-in-out}.ball:nth-child(3){background:#008597;-webkit-animation:right 1.05s infinite ease-in-out;-moz-animation:right 1.05s infinite ease-in-out;animation:right 1.05s infinite ease-in-out}.ball:nth-child(4){background:#fc0;-webkit-animation:left 1.15s infinite ease-in-out;-moz-animation:left 1.15s infinite ease-in-out;animation:left 1.15s infinite ease-in-out}.ball:nth-child(5){background:#2d3443;-webkit-animation:right 1.1s infinite ease-in-out;-moz-animation:right 1.1s infinite ease-in-out;animation:right 1.1s infinite ease-in-out}.ball:nth-child(6){background:#ff7c35;-webkit-animation:left 1.05s infinite ease-in-out;-moz-animation:left 1.05s infinite ease-in-out;animation:left 1.05s infinite ease-in-out}.ball:nth-child(7){background:#4d407c;-webkit-animation:right 1s infinite ease-in-out;-moz-animation:right 1s infinite ease-in-out;animation:right 1s infinite ease-in-out}@-webkit-keyframes right{0%,100%{-webkit-transform:translate(-15px)}50%{-webkit-transform:translate(15px)}}@-webkit-keyframes left{0%,100%{-webkit-transform:translate(15px)}50%{-webkit-transform:translate(-15px)}}@-moz-keyframes right{0%,100%{-moz-transform:translate(-15px)}50%{-moz-transform:translate(15px)}}@-moz-keyframes left{0%,100%{-moz-transform:translate(15px)}50%{-moz-transform:translate(-15px)}}@keyframes right{0%,100%{transform:translate(-15px)}50%{transform:translate(15px)}}@keyframes left{0%,100%{transform:translate(15px)}50%{transform:translate(-15px)}}</style>
</head>
<body>
  <center><h1><?php _e('Maintenance'); ?></h1></center>
  <p align="center"><?php _e('Briefly unavailable for scheduled maintenance. Check back in a minute.'); ?></p>
  <div class="container"><div class="ball"></div><div class="ball"></div><div class="ball"></div><div class="ball"></div><div class="ball"></div><div class="ball"></div><div class="ball"></div></div>
  <script>var maintenance_check=function(){var n=new XMLHttpRequest;n.open("HEAD",window.location,!0),n.onload=function(){this.status>=200&&this.status<400?window.location.reload():setTimeout(maintenance_check,5000)},n.onerror=function(){setTimeout(maintenance_check,5000)},n.send()};maintenance_check();</script>
</body>
</html>

Aunque si ese, que es sencillo y con un poco de formato te ha gustado, este tampoco se queda atrás.

<?php
wp_load_translations_early();
$protocol = wp_get_server_protocol();
header($protocol.' 503 Service Unavailable', true, 503);
header('Retry-After: 60');
header('Content-Type: text/html; charset=utf-8');
?>
<!DOCTYPE html>
<html>
<head>
  <title><?php _e('Maintenance'); ?></title>
  <style>body{background-color:#012;background-image:url(https://cssanimation.rocks/demo/starwars/images/bg.jpg);background-size:33%;background-repeat:repeat;min-height:2025px;color:#fff}.system{position:relative;top:0;left:0;width:100%;height:100%;-webkit-transform:scale(.75);transform:scale(.75)}.sun{width:144px;height:144px;border-radius:72px;position:absolute;top:1066.67px;left:50%;margin:-72px;background-image:url(https://sdo.gsfc.nasa.gov/assets/img/latest/latest_256_HMIIF.jpg);background-size:144px;background-repeat:no-repeat}.mer,.mer-path{border-radius:50%;position:absolute;top:1066.67px;left:50%}@-webkit-keyframes rot-mer{from{-webkit-transform:rotate(0) translatey(-84px) rotate(0)}to{-webkit-transform:rotate(360deg) translatey(-84px) rotate(-360deg)}}@-keyframes rot-mer{from{-webkit-transform:rotate(0) translatey(-84px) rotate(0);transform:rotate(0) translatey(-84px) rotate(0)}to{-webkit-transform:rotate(360deg) translatey(-84px) rotate(-360deg);transform:rotate(360deg) translatey(-84px) rotate(-360deg)}}.mer{width:3.5px;height:3.5px;background-color:#888;margin:-1.75px;-webkit-animation:rot-mer .88s infinite linear;animation:rot-mer .88s infinite linear;z-index:200}.mer-path{width:168px;height:168px;z-index:100;margin:-84px;border:1px solid #444}.ven,.ven-path{border-radius:50%;position:absolute;top:1066.67px;left:50%}@-webkit-keyframes rot-ven{from{-webkit-transform:rotate(0) translatey(-90px) rotate(0)}to{-webkit-transform:rotate(360deg) translatey(-90px) rotate(-360deg)}}@-keyframes rot-ven{from{-webkit-transform:rotate(0) translatey(-90px) rotate(0);transform:rotate(0) translatey(-90px) rotate(0)}to{-webkit-transform:rotate(360deg) translatey(-90px) rotate(-360deg);transform:rotate(360deg) translatey(-90px) rotate(-360deg)}}.ven{width:5.5px;height:5.5px;background-color:#f5f9be;margin:-2.75px;-webkit-animation:rot-ven 2.25s infinite linear;animation:rot-ven 2.25s infinite linear;z-index:200}.ven-path{width:180px;height:180px;z-index:100;margin:-90px;border:1px solid #444}.ear,.ear-path{border-radius:50%;position:absolute;top:1066.67px;left:50%}@-webkit-keyframes rot-ear{from{-webkit-transform:rotate(0) translatey(-102px) rotate(0)}to{-webkit-transform:rotate(360deg) translatey(-102px) rotate(-360deg)}}@-keyframes rot-ear{from{-webkit-transform:rotate(0) translatey(-102px) rotate(0);transform:rotate(0) translatey(-102px) rotate(0)}to{-webkit-transform:rotate(360deg) translatey(-102px) rotate(-360deg);transform:rotate(360deg) translatey(-102px) rotate(-360deg)}}.ear{width:7px;height:7px;background-color:#4b94f9;margin:-3.5px;-webkit-animation:rot-ear 3.65s infinite linear;animation:rot-ear 3.65s infinite linear;z-index:200}.ear-path{width:204px;height:204px;z-index:100;margin:-102px;border:1px solid #444}.mar,.mar-path{border-radius:50%;position:absolute;top:1066.67px;left:50%}@-webkit-keyframes rot-mar{from{-webkit-transform:rotate(0) translatey(-118px) rotate(0)}to{-webkit-transform:rotate(360deg) translatey(-118px) rotate(-360deg)}}@-keyframes rot-mar{from{-webkit-transform:rotate(0) translatey(-118px) rotate(0);transform:rotate(0) translatey(-118px) rotate(0)}to{-webkit-transform:rotate(360deg) translatey(-118px) rotate(-360deg);transform:rotate(360deg) translatey(-118px) rotate(-360deg)}}.mar{width:6px;height:6px;background-color:#dd411a;margin:-3px;-webkit-animation:rot-mar 6.87s infinite linear;animation:rot-mar 6.87s infinite linear;z-index:200;background-image:-webkit-repeating-linear-gradient(top,#fff,#fff 1px,transparent 1px,transparent 5px);background-image:repeating-linear-gradient(to bottom,#fff,#fff 1px,transparent 1px,transparent 5px)}.mar-path{width:236px;height:236px;z-index:100;margin:-118px;border:1px solid #444}.jup,.jup-path{border-radius:50%;position:absolute;top:1066.67px;left:50%}@-webkit-keyframes rot-jup{from{-webkit-transform:rotate(0) translatey(-228px) rotate(0)}to{-webkit-transform:rotate(360deg) translatey(-228px) rotate(-360deg)}}@-keyframes rot-jup{from{-webkit-transform:rotate(0) translatey(-228px) rotate(0);transform:rotate(0) translatey(-228px) rotate(0)}to{-webkit-transform:rotate(360deg) translatey(-228px) rotate(-360deg);transform:rotate(360deg) translatey(-228px) rotate(-360deg)}}.jup{width:70px;height:70px;background-color:#eaad3b;margin:-35px;-webkit-animation:rot-jup 43.32s infinite linear;animation:rot-jup 43.32s infinite linear;z-index:200;background-image:-webkit-repeating-linear-gradient(84deg,#797663 22px,#e1dcde 16px,#c3a992 30px,#e9ece2 30px);background-image:repeating-linear-gradient(6deg,#797663 22px,#e1dcde 16px,#c3a992 30px,#e9ece2 30px)}.jup-path{width:456px;height:456px;z-index:100;margin:-228px;border:1px solid #444}.sat,.sat-path{border-radius:50%;position:absolute;top:1066.67px;left:50%}@-webkit-keyframes rot-sat{from{-webkit-transform:rotate(0) translatey(-362px) rotate(0)}to{-webkit-transform:rotate(360deg) translatey(-362px) rotate(-360deg)}}@-keyframes rot-sat{from{-webkit-transform:rotate(0) translatey(-362px) rotate(0);transform:rotate(0) translatey(-362px) rotate(0)}to{-webkit-transform:rotate(360deg) translatey(-362px) rotate(-360deg);transform:rotate(360deg) translatey(-362px) rotate(-360deg)}}.sat{width:58px;height:58px;background-color:#d6cd93;margin:-29px;-webkit-animation:rot-sat 107.59s infinite linear;animation:rot-sat 107.59s infinite linear;z-index:200}.sat-path{width:724px;height:724px;z-index:100;margin:-362px;border:1px solid #444}.ura,.ura-path{border-radius:50%;position:absolute;top:1066.67px;left:50%}@-webkit-keyframes rot-ura{from{-webkit-transform:rotate(0) translatey(-648px) rotate(0)}to{-webkit-transform:rotate(360deg) translatey(-648px) rotate(-360deg)}}@-keyframes rot-ura{from{-webkit-transform:rotate(0) translatey(-648px) rotate(0);transform:rotate(0) translatey(-648px) rotate(0)}to{-webkit-transform:rotate(360deg) translatey(-648px) rotate(-360deg);transform:rotate(360deg) translatey(-648px) rotate(-360deg)}}.ura{width:26px;height:26px;background-color:#bfeef2;margin:-13px;-webkit-animation:rot-ura 306.87s infinite linear;animation:rot-ura 306.87s infinite linear;z-index:200}.ura-path{width:1296px;height:1296px;z-index:100;margin:-648px;border:1px solid #444}.nep,.nep-path{border-radius:50%;position:absolute;top:1066.67px;left:50%}@-webkit-keyframes rot-nep{from{-webkit-transform:rotate(0) translatey(-972px) rotate(0)}to{-webkit-transform:rotate(360deg) translatey(-972px) rotate(-360deg)}}@-keyframes rot-nep{from{-webkit-transform:rotate(0) translatey(-972px) rotate(0);transform:rotate(0) translatey(-972px) rotate(0)}to{-webkit-transform:rotate(360deg) translatey(-972px) rotate(-360deg);transform:rotate(360deg) translatey(-972px) rotate(-360deg)}}.nep{width:24px;height:24px;background-color:#363ed7;margin:-12px;-webkit-animation:rot-nep 601.9s infinite linear;animation:rot-nep 601.9s infinite linear;z-index:200}.nep-path{width:1944px;height:1944px;z-index:100;margin:-972px;border:1px solid #444}.plu,.plu-path{border-radius:50%}@-webkit-keyframes rot-plu{from{-webkit-transform:rotate(0) translatey(-1246px) rotate(0)}to{-webkit-transform:rotate(360deg) translatey(-1246px) rotate(-360deg)}}@-keyframes rot-plu{from{-webkit-transform:rotate(0) translatey(-1246px) rotate(0);transform:rotate(0) translatey(-1246px) rotate(0)}to{-webkit-transform:rotate(360deg) translatey(-1246px) rotate(-360deg);transform:rotate(360deg) translatey(-1246px) rotate(-360deg)}}.plu{width:3px;height:3px;background-color:#963;position:absolute;left:50%;margin:-1.5px;-webkit-animation:rot-plu 904.65s infinite linear;animation:rot-plu 904.65s infinite linear;z-index:200}.dem,.jove,.lune,.pho{background-color:#fff;left:50%;position:absolute}.plu-path{width:2492px;height:2492px;z-index:100;position:absolute;left:50%;margin:-1246px;border:1px solid #444}@-webkit-keyframes rot-lune{from{-webkit-transform:rotate(0) translatey(-7px) rotate(0)}to{-webkit-transform:rotate(360deg) translatey(-7px) rotate(-360deg)}}@-keyframes rot-lune{from{-webkit-transform:rotate(0) translatey(-7px) rotate(0);transform:rotate(0) translatey(-7px) rotate(0)}to{-webkit-transform:rotate(360deg) translatey(-7px) rotate(-360deg);transform:rotate(360deg) translatey(-7px) rotate(-360deg)}}.lune{width:2px;height:2px;top:50%;margin:-1.5px;-webkit-animation:rot-lune .27s infinite linear;animation:rot-lune .27s infinite linear}.dem,.pho{margin:-1px}@-webkit-keyframes rot-pho{from{-webkit-transform:rotate(0) translatey(-7px) rotate(0)}to{-webkit-transform:rotate(360deg) translatey(-7px) rotate(-360deg)}}@-keyframes rot-pho{from{-webkit-transform:rotate(0) translatey(-7px) rotate(0);transform:rotate(0) translatey(-7px) rotate(0)}to{-webkit-transform:rotate(360deg) translatey(-7px) rotate(-360deg);transform:rotate(360deg) translatey(-7px) rotate(-360deg)}}@-webkit-keyframes rot-dem{from{-webkit-transform:rotate(0) translatey(-9px) rotate(0)}to{-webkit-transform:rotate(360deg) translatey(-9px) rotate(-360deg)}}@-keyframes rot-dem{from{-webkit-transform:rotate(0) translatey(-9px) rotate(0);transform:rotate(0) translatey(-9px) rotate(0)}to{-webkit-transform:rotate(360deg) translatey(-9px) rotate(-360deg);transform:rotate(360deg) translatey(-9px) rotate(-360deg)}}.dem,.pho{width:1px;height:1px;top:50%}.pho{-webkit-animation:rot-pho .15s infinite linear;animation:rot-pho .15s infinite linear}.dem{-webkit-animation:rot-dem .2s infinite linear;animation:rot-dem .2s infinite linear}.jove{width:2px;height:2px;top:35px}@-webkit-keyframes rot-io{from{-webkit-transform:rotate(0) translatey(-39px) rotate(0)}to{-webkit-transform:rotate(360deg) translatey(-39px) rotate(-360deg)}}@-keyframes rot-io{from{-webkit-transform:rotate(0) translatey(-39px) rotate(0);transform:rotate(0) translatey(-39px) rotate(0)}to{-webkit-transform:rotate(360deg) translatey(-39px) rotate(-360deg);transform:rotate(360deg) translatey(-39px) rotate(-360deg)}}@-webkit-keyframes rot-eur{from{-webkit-transform:rotate(0) translatey(-41px) rotate(0)}to{-webkit-transform:rotate(360deg) translatey(-41px) rotate(-360deg)}}@-keyframes rot-eur{from{-webkit-transform:rotate(0) translatey(-41px) rotate(0);transform:rotate(0) translatey(-41px) rotate(0)}to{-webkit-transform:rotate(360deg) translatey(-41px) rotate(-360deg);transform:rotate(360deg) translatey(-41px) rotate(-360deg)}}@-webkit-keyframes rot-gan{from{-webkit-transform:rotate(0) translatey(-45px) rotate(0)}to{-webkit-transform:rotate(360deg) translatey(-45px) rotate(-360deg)}}@-keyframes rot-gan{from{-webkit-transform:rotate(0) translatey(-45px) rotate(0);transform:rotate(0) translatey(-45px) rotate(0)}to{-webkit-transform:rotate(360deg) translatey(-45px) rotate(-360deg);transform:rotate(360deg) translatey(-45px) rotate(-360deg)}}@-webkit-keyframes rot-cal{from{-webkit-transform:rotate(0) translatey(-53px) rotate(0)}to{-webkit-transform:rotate(360deg) translatey(-53px) rotate(-360deg)}}@-keyframes rot-cal{from{-webkit-transform:rotate(0) translatey(-53px) rotate(0);transform:rotate(0) translatey(-53px) rotate(0)}to{-webkit-transform:rotate(360deg) translatey(-53px) rotate(-360deg);transform:rotate(360deg) translatey(-53px) rotate(-360deg)}}.io{-webkit-animation:rot-io .2s infinite linear;animation:rot-io .2s infinite linear}.eur{-webkit-animation:rot-eur .35s infinite linear;animation:rot-eur .35s infinite linear}.gan{-webkit-animation:rot-gan .7s infinite linear;animation:rot-gan .7s infinite linear}.cal{-webkit-animation:rot-cal 1.65s infinite linear;animation:rot-cal 1.65s infinite linear}.spot{position:absolute;width:16px;height:12px;border-radius:8px/6px;top:45px;left:50%;background-color:#bc833b;box-shadow:0 0 5px #e1dcde;border:1px solid #e1dcde;box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;z-index:300}.nep .spot{background-color:#29319d;border:0;box-shadow:none;top:50%;left:45%;width:10px;height:6px;margin:-2px;border-radius:5px/3px;border-left:solid 1px #7ed6fe}div[class$="-ring"]{border-radius:50%;position:absolute;top:50%;left:50%;opacity:.7;-webkit-transform:rotatex(45deg);transform:rotatex(45deg)}.a-ring{border:5px solid #96866f;width:119px;height:119px;margin:-64.5px}.b-ring{border:10px solid #554c3c;width:104px;height:104px;margin:-62px}.c-ring{border:9px solid #574f4a;width:95px;height:95px;margin:-56.5px}.f-ring{border:2px solid #908e8d;width:133px;height:133px;margin:-68.5px}.e-ring{border:7px solid #908e8d;width:76px;height:76px;margin:-45px;-webkit-transform:rotatex(0) rotatey(89deg)!important;transform:rotatex(0) rotatey(89deg)!important}.plu,.plu-path{top:1354.07px}</style>
</head>
<body>
  <center><h1><?php _e('Maintenance'); ?></h1></center>
  <p align="center"><?php _e('Briefly unavailable for scheduled maintenance. Check back in a minute.'); ?></p>
  <div class="system"><div class="sun"></div><div class="mer-path"></div><div class="mer"></div><div class="ven-path"></div><div class="ven"></div><div class="ear-path"></div><div class="ear"><div class="lune"></div></div><div class="mar-path"></div><div class="mar"><div class="pho"></div><div class="dem"></div></div><div class="jup-path"></div><div class="jup"><div class="spot"></div><div class="jove io"></div><div class="jove eur"></div><div class="jove gan"></div><div class="jove cal"></div></div><div class="sat-path"></div><div class="sat"><div class="f-ring"></div><div class="a-ring"></div><div class="b-ring"></div><div class="c-ring"></div></div><div class="ura-path"></div><div class="ura"><div class="e-ring"></div></div><div class="nep-path"></div><div class="nep"><div class="spot"></div></div><div class="plu-path"></div><div class="plu"></div></div>
  <script>var maintenance_check=function(){var n=new XMLHttpRequest;n.open("HEAD",window.location,!0),n.onload=function(){this.status>=200&&this.status<400?window.location.reload():setTimeout(maintenance_check,5000)},n.onerror=function(){setTimeout(maintenance_check,5000)},n.send()};maintenance_check();</script>
</body>
</html>

Ahora ya tienes unas primeras plantillas para optimizar tu WordPress cuando esté en mantenimiento y tus usuarios no vean un feo texto.

WPdanger, análisis de seguridad para WordPress

Un clásico de los sitios web que usan un CMS de fondo es la falta de actualización de los mismos. Esto hace que si en un par de meses tu sitio está sin actualizar sea objetivo de cualquier ataque, ya que todos los problemas que puedan haber, estarán.

Si a esta preocupación personal le sumamos que en verano suelo hacer “cositas por entretenerme”, salen proyectos como WPdanger, un sitio web en el que pones la dirección de tu sitio en WordPress y te da algunas vulnerabilidades o te puede servir para encontrar problemas que puedas tener y que todos pueden verificar.

Al principio comencé usando WPscan para hacer algunas pruebas, pero aunque en particular funcionaba, a lo grande ya no era tan simple. Así que monté un primer sistema que mostraba los resultados por pantalla web, posteriormente comené a procesarlos y al final ha salido una web en la que analiza más de lo que hacía al principio (que era puramente reactivo) a algo un poco más decente y que da más datos, además de mostrar enlaces a todos aquellos problemas que pueden aparecer.

Pero esto era poco… si cualquiera tiene acceso a este tipo de herramientas ¿cómo evitar que los datos que aparecen sean útiles para prevenir ataques? Obviamente la primera fase era evitar enseñar lo que no se tiene que enseñar, es decir, que la herramienta crea que lo que realmente hay no esté. Así, si un hacker usa estas herramientas, y ve que aparentemente no hay mucho que hacer en el sitio, pase de él. Esto me ha llevado durante algunos días a hacer y hacer análisis hasta poder ir bloqueando aquellos elementos que bloqueasen ataques pero hiciesen que la web siguiera funcionando. Tras varias horas revisando y analizando y probando con mi sitio, llegué a varias conclusiones.

La primera de ellas es que WordPress funciona mejor con nginx que con Apache HTTPD. En principio debería dar igual, pero a la hora de configurar elementos ys eguridad, ya no tanto. Entre uno y otro, me quedo con nginx. Lo segundo es que hay que montar PHP 7, principalmente por temas de rendimiento. A partir de esta combinación, podemos comenzar a trabajar.

La segunda es que hay plugins (muy utilizados) que no piensan en la seguridad, no permiten desactivar determinados elementos y que ponen en riesgo todo t sitio. El principal que me he encontrado es el Yoast SEO. Me gusta, no me importa que tenga código que ponga que lo usas, pero por favor, no indiquemos la versión, o al menos que la versión sea un eleemnto que se pueda desactivar. Como digo, es el plugin más inseguro (desde ese punto de vista) que he encontrado.

La tercera es que el hecho de que WordPress sea tan estándar y tan sencillo, hace que se puedan detectar versiones de plugins y plantillas de forma extremadamente sencilla (y sobre todo, de forma automática). Obviamente hay que encontrar un mix entre funcionalidad y seguridad. Me ha costado, pero he acabado encontrándolo.

El cuarto es que las configuraciones de seguridad que hay por Internet sobre WordPress se quedan extremadamente cortos. Es obvio que hay que informar, siempre lo primero, en que tu WordPress esté actualizado, obvio ye s así, pero por ejemplo, en todos los manuales se habla del famoso “usuario admin” que desde hace muchísimas versiones ya no viene por defecto. Está bien decir que no se use, pero han pasado años de que sea el mayor problema de seguridad de los usuarios. Lo que más me molesta es que no se explique esto, que es un tema histórico y que una instalación nueva no debería preocuparse en exceso por este asunto.

El quinto es que me ha parecido extraño que los grandes proveedores de hosting especializados en WordPress no den soluciones de seguridad sencillas más avanzadas, sobre todo en la parte preventiva.

Obviamente, no hay sitios 100% seguros, ni pretendo que los haya, pero sí que la prevención de la que siempre se habla en seguridad, se aplique. No tiene sentido decir que tienes un Firewall si luego puedo saber la lista de plugins que tienes instalados, o qué plantillas usas, y mucho menos saber qué versiones son y si están al día o no, incluyendo al núcleo.

¿Qué he aprendido con todo esto? A mejorar la ocultaciónd e información de la manera más simple posible que he encontrado, y principalmente poner difícil a los demás saber qué uso o dejo de usar. Un ejemplo, ahora mismo, es que si lanzo un análisis contra mi sitio, hace unos días me decía qué versión de WordPress tenía (exactamente), toda la lista de plugins, con sus versiones y sabiendo sie staban actualizados o no, y lo mismo con las plantillas… Ahora me dice una versión casi exacta de la que tengo en realidad de WordPress, pero ya no me dice qué plugins o plantilla tengo.

Esto no significa que si te miras un poco el código no se pueda saber, pero el hecho de que “de forma automática nos e sepa” me hace sentir un poco mejor, porque mucha gente que quiera hacer maldades lo tendrá ligeramente más difícil o, como mínimo, tendrá que dedicarle tiempo humano (y no tiempo máquina) para hacer maldades (a alguien que, la verdad, dudo que le aporte o vaya a conseguir nada útil).

Para acabar, tengo escrito un ¿folleto? de 15 páginas sobre seguridad de WordPress en el que explico con pelos y señales cómo solventar prácticamente todos estos problemas. La cuestión es si debería publicarlo por completo o parcialmente y plantear como vía de negocio / modelo de vida (y más ahora que no estoy trabajando en ningún proyecto y he vuelto al autonomismo) y de esa forma, ofreciendo uns ervicio barato, ofrecer la posibilidad de montar WordPress de forma segura a quien no sepa qué hacer con su sitio web. Aún así, como siempre, si alguien necesita ayuda con algo, parcialmente como parte de la comunidad, parcialmente como modelo de vida, estoy aquí para ayudar.

Consejos básicos de seguridad para WordPress

WordPress es seguro. Esa es una máxima que normalmente los seres humanos rompemos y convertimos el software en algo menos seguro de lo que debería.

En la presentación que hice ayer tuve la oportunidad de presentar algunas cosas que todo el mundo explica sobre seguridad, otras que se dicen pero no se hacen y otras tantas que son más desconocidas o que deberían hacerse y no se hacen.

Además, como tema máximo, comenté sobre el uso del 2FA (segunda autenticación) que ayuda a bloquear intrusos aunque te roben tus claves.

Aquí os dejo la descarga del PDF de mi parte de la presentación (Consejos de Seguridad para WordPress), en la que hay bastantes códigos para el wp-config.php, además de algunos plugins que te pueden ayudar a proteger un poco más el sistema.