Revista Comunicación

Seguridad en WordPress

Por Comercialseo @ComercialSEO

Muy buenas a todos, voy a crear esta entrada para que sirva como índice de seguridad para WordPress, siempre que queramos dejar una instalación de wordpress totalmente segura y reforzar de esa forma las capas de seguridad que posee ya de por sí este framework de trabajo. Ya sea por que estemos controlando una tienda online o base de datos sensible, por ejemplo, o por que queramos tener la máxima seguridad en nuestro sistema, seguro que encontraremos interesantes algunos de los puntos que se van a detallar a continuación.
Comencemos!

Antes de realizar ninguna de las acciones que muestro a continuación es importante que realices una copia de seguridad de todo el árbol de archivos de tu página web y de la base de datos, la base de datos compímela en .zip o .gzip, no tienen por que pasar nada pero puede haber incompatibilidades con plugins o themes y de esa forma siempre vamos a poder volver al punto de partida si esto ocurre.

Las cifras de WordPress en 2013

Seguridad en WordPress
El fundador del proyecto WordPress hacía públicas las cifras a finales del 2013 sobre el uso y expansión del mismo y la verdad que son totalmente abrumadoras, más de 69Millones de web's en todo el mundo funcionan con wordpress, lo que supone el 19% del total de páginas del planeta, con más de 10.000 temas disponibles y más de 25.000 plugins en funcionamiento y a nuestra disposición.

Esta posición de clara ventaja con respecto al resto hacen que wordpress sea el CMS con más apoyo a la comunidad del momento, con miles de desarrolladores trabajando en su código y mejoras pero también tiene un lado negativo, es uno de los más atacado por hackers y lammers, al ser como hemos dicho uno de los más usados.

Bien, existen formas para poner trabas a esos posibles malintencionados visitantes, o por lo menos para complicarles las cosas todo lo que podamos como vamos a ver a continuación.
A diferencia de lo que pueda parecer, lo que hace más vulnerable a un sistema wordpress por lo general suelen ser factores ajenos al propio wordpress, por ejemplo.
La seguridad y calidad del hospedaje o servidor en el que esté instalado representa un riesgo de potencial magnitud, y es el principal agujero por el que se van a poder colar en nuestro sistema, por ese motivo serán siempre más fiables los hospedajes de pago con uno niveles de seguridad aceptables que los gratuitos.
Otro punto muy importante será tener el sistema, themes y plugins siempre actualizados ya que cada nueva vulnerabilidad que se descubre por lo general se corrige con una actualización, si alguien conoce las vulnerabilidades de alguna versión en concreto de estos elementos y estamos usando esa misma versión va a tener las puertas abiertas y es algo que debemos controlar.
Otro riesgo potencial sería el de la inyección de código fuente en nuestro sistema a través de alguno de los formularios existentes en el mismo, esto se puede tapar en gran medida haciendo prácticamente imposible la inyección de código como veremos después.
Por último, el acceso al sistema por medio de ataques de fuerza bruta será otro punto a vigilar, estos ataques son por medio de repeticiones e intentos constantes de acceder con nuestra contraseña, es por ello que esta deberá ser siempre lo más robusta posible reduciendo así la posibilidad de que el atacante la descubra.
Lo primero que hará un atacante para ver si puede manipular nuestro sistema será ver si conoce el prefijo de las tablas de mysql que tenemos instaladas, durante la instalación de WP este nos brinda la posibilidad de cambiar ese prefijo en el archivo wp-config.php concretamente en la línea de código nº62
$table_prefix = 'wp_';
Ahí es importante que cambiemos ese código por algo como lo siguiente

$table_prefix = 'wp_Wb1′;
O lo que queramos después del wp_ o incluso sin el wp_ podemos poner un prefijo cualquiera por ejemplo:

$table_prefix = 'Wb1_';
De esa forma será más difícil conocer el nombre de nuestras tablas en mysql y en consecuencia de poder inyectar código en nuestra base de datos o incluso de manipular alguno de los registros.

Si ya teníamos instalado el sistema y no cambiamos el prefijo lo podemos cambiar de forma sencilla con este plugin:
https://wordpress.org/plugins/db-prefix-change/

Tras cambiar el prefijo podemos desinstalar y borrar el plugin para que quede totalmente sellado y no se pueda ver lo que hemos hecho.
Del mismo modo, cuando realicemos una instalación nueva de WP será muy importante cambiar las claves de encriptación del mismo para que sea prácticamente imposible que puedan encriptar las mismas contraseñas y datos sensibles que estemos usando.
Esto lo podemos hacer antes de realizar la instalación en el archivo wp-config.php, en la línea nº 45 vemos que tenemos un comentario que dice:
* Claves únicas de autentificación.
Bien las líneas de código que se encuentran un poco más abajo son precísamente esas claves:

define('AUTH_KEY', 'pon aquí tu frase aleatoria'); // Cambia esto por tu frase aleatoria.
define('SECURE_AUTH_KEY', 'pon aquí tu frase aleatoria'); // Cambia esto por tu frase aleatoria.
define('LOGGED_IN_KEY', 'pon aquí tu frase aleatoria'); // Cambia esto por tu frase aleatoria.
define('NONCE_KEY', 'pon aquí tu frase aleatoria'); // Cambia esto por tu frase aleatoria.
define('AUTH_SALT', 'pon aquí tu frase aleatoria'); // Cambia esto por tu frase aleatoria.
define('SECURE_AUTH_SALT', 'pon aquí tu frase aleatoria'); // Cambia esto por tu frase aleatoria.
define('LOGGED_IN_SALT', 'pon aquí tu frase aleatoria'); // Cambia esto por tu frase aleatoria.
define('NONCE_SALT', 'pon aquí tu frase aleatoria'); // Cambia esto por tu frase aleatoria.

Donde dice 'pon aquí tu frase aleatoria' es donde debemos colocar los caracteres que formen cada una de las llaves de encriptación, WP nos ofrece la posibilidad de generar estas de forma automática desde Internet siendo mucho más seguras al estar formadas por números, caracteres y símbolos, desde la url
https://api.wordpress.org/secret-key/1.1/salt/
Podemos generarlas, si entramos vemos que lo único que aparece en esa pantalla es lo siguiente:

define('AUTH_KEY',         'S:RO+p?Vx4r`co} TdK`(!HZ<+O_4EtanF0d_o/*4%-N-!44rgkr_&se/}W`5EU>');
define('SECURE_AUTH_KEY',  'aN]s=3F1{~!5=zeza#&):oJZM+_KVNmI&6sD!1&||^QD)g~@S(b{N3t|}qIO+Bj-');
define('LOGGED_IN_KEY',    '&pao4+ nD()~lWANorO~|(mXS>UOirdxryrN+np{-vOs~< ,Z9bS?eH+H]aXu4@ ');
define('NONCE_KEY',        'z[vq.;Z,PB/1|#(Syw_:|O9h@q,BbatwFuyzz@b9QaO)ot:[email protected]@D+ttb8{dokD');
define('AUTH_SALT',        'u]MTiVc6u}^b7QWlvlLk#T0R<,>f1MAdfJepd (p(1 j_|*h8B&zAPl.rbm|{etu');
define('SECURE_AUTH_SALT', '`YS*RQ33184I-~o>=_z9wSKLpOPz!ZB09!rm$F3MoxM[h+4/!S6]$; MEf,m.hD8');
define('LOGGED_IN_SALT',   'tV(*7pHiwW%Uu}uy4q:{Flylg47b}q&jFx{|#g-l7xcN0dcUrPTe{*J1$|!^NG-,');
define('NONCE_SALT',       '{~e9.eP}<fpLde|>`V;x.0K3Qf,>F+lCsE0@cF~heP9QP3C=ewp,/>PG4NkP;Y=!');

Basta con sustitutir unas por otras y ya lo tenemos.
Existen algunos archivos innecesarios que debemos eliminar tras una instalación de wordpress y después de alguna actualización del core del sistema, veamos cuales:

install.php
Este archivo que se encuentra en la carpeta de wordpress /NombreDeCarpetaDelHosting/wp-admin/ es el que usa el sistema cuando realiza una instalación nueva y cuando realiza actualizaciones, pero es importante que si por ejemplo el servidor de bases de datos se encuentra caído, el primer usuario que entre en la página va a tener a su alcance la interface de instalación de WP y podría causarnos algún problema si rellena todos los datos e intenta realizar la instalación de nuevo. Lo mejor es eliminarlo y proteger después las posibles nuevas creaciones del mismo.
Para eliminarlo basta con acceder a la carpeta y borrar el archivo /NombreDeCarpetaDelHosting/wp-admin/install.php, no hay ningún problema después para posibles actualizaciones lo que vamos a hacer en lugar de estar siempre entrando y borrándolo será protegerlo para que no lo pueda usar ningún visitante de la web.
Para protegerlo haremos lo siguiente, crearemos un archivo .htaccess con el siguiente código dentro de la carpeta /NombreDeCarpetaDelHosting/wp-admin/

<Files .htaccess>
order allow,deny
deny from all
</Files>

<Files install.php>
order allow,deny
deny from all
</Files>

De esa forma aunque se vuelva a crear no será accesible por nadie excepto por el propio servidor de datos.

wp-config.php y wp-config-sample.php
Los archivos de configuración de WP los puedes encontrar en la carpeta general de WP /NombreDeCarpetaDelHosting/ son unos de los más importantes, ya que contienen las claves de encriptación de nuestro sistema y las de conexión con la base de datos, de vital importancia que estos datos no puedan ser accesibles nada más que por el administrador y el propio sistema. El segundo wp-config-sample.php si está en el servidor lo mejor será borrarlo por si tiene los datos reales, no es necesario que esté allí, el primero wp-config.php no lo borraremos bajo ningún concepto, en su lugar protegeremos su acceso y restringiremos sus permisos de la siguiente manera.
Crearemos un archivo .htaccess en la carpeta general /NombreDeCarpetaDelHosting/ o, en caso de que este archivo ya exista incluiremos el siguiente código al final del mismo:

<Files .htaccess> 
order allow,deny deny from all 
</Files>

<Files wp-config.php>
order allow,deny
deny from all
</Files>

readme.html
Este archivo se encuentra en la carpeta raíz del sistema /NombreDeCarpetaDelHosting/ y es totalmente inecesario, es más lo único que podría hacer es mostrar a un posible atacante la versión de WP que tenemos instalado en nuestro sistema, algo que si podemos es mejor que tratemos de evitar, lo eliminaremos sin ningún problema

Protección de archivos y carpetas del sistema WP

Las carpetas y archivos del sistema también deben tener los permisos a nivel de servidor bien configurados, los permisos que debemos mirar son estos:

- Los permisos de la carpeta raíz o general de WordPress deben ser 0755

- Los permisos de archivos:

<<.htaccess>> 0644
<<.readme.html>> 0440 (aunque este archivo como hemos dicho lo mejor es borrarlo también)
<<wp-config.php>> 0644

- Los permisos de las carpetas del sistema:

<<wp-admin>> 0755
<<wp-content>> 0755
<<wp-includes>> 0755
<<wp-content/plugins>> 0755
<<wp-content/uploads>> 0755

Con estos permisos bien asignados estamos protegiendo de mejor manera nuestro sistema.
Es importante que sepamos cómo gestiona WP los permisos o roles de usuarios, en concreto existen cuatro tipos de usuarios en el sistema, cada uno con diferentes tipos de permisos:

Usuario Super Administrador
Este usuario por lo general suele ser el primero que se crea durante la instalación del sistema y es el que más permisos tiene dentro del mismo, tiene todos los permisos que existen, en consecuencia, es el que más tenemos que proteger y con el que más cuidado tenemos que tener.
Como primera medida de protección está la de poner un nombre de usuario específico y creado por nosotros mismos, no vale eso de llamarle por ejemplo admin ya que será muy obvio y nos podría dar problemas después.
Como segunda medida está la de poner una contraseña robusta para evitar ataques de fuerza bruta, una buena contraseña ha de estar formada por números, caracteres y si es posible algún signo.
También es interesante que en las opciones del perfil de usuarios marquemos como nombre visible el nombre y apellidos que hayamos puesto en el formulario, nunca el nombre de usuario que es el que suele dejar WP por defecto, si no lo cambiamos cuando comentemos algo o en el apartado autor de entrada se podrá ver el nombre de usuario y un atacante ya sabrá el 50% de nuestros datos de acceso al sistema. Para cambiar esto basta con ir a Usuarios > Mi perfil y cambiar donde dice:

Seguridad en WordPress

Administradores
Los usuarios administradores poseen prácticamente los mismos permisos que el SuperAdmin, por ello es preciso que sólo sean administradores aquellos usuarios que realmente puedan trabajar a nivel de programación y edición en la web, si por ejemplo damos de alta como administrador a un autor, este después será capaz de cambiar contraseñas y de administrar algunos puntos delicados del sistema, lo mejor es dar a cada usuario los permisos justos para evitar problemas innecesarios.

Editores
Los perfiles editores son muy interesantes, dado que van a poder controlar internamente los contenidos que muestra la web sin poder acceder a configuraciones o administración de la web, un usuario que no tenga que hacer cambios en diseño o programación pero que sí pueda borrar páginas o cambiar contenido de las mismas debería ser editor de la web.

Autores
Los autores van a tener los mismos permisos que los editores pero sólo en el contenido que hayan creado ellos mismos, no en el de los demás, y sólo en contenido relacionado con entradas o post, nunca en las páginas, enlaces, y demás contenido que puede mostrar WP.

Contribuidores
Los usuarios contribuidores bajo mi punto de vista no deberían existir, están ahí por si queremos dar la opción de que un usuario pueda leer entradas creadas por otro y editar estas entradas o borrarlas, nunca las podrán crear ellos mismos, en concreto los permisos que tendrán serán los de editar, borrar y leer entradas. Como digo es un perfil que no tiene mucho sentido.

Suscriptores
Por último el suscriptor, este perfil lo único que va a permitir es leer entradas o contenidos protegidos por login, es útil si por ejemplo tenemos contenido en la web que puede ser accedido sólo por usuarios que hayan hecho login, estos usuarios tendrán la opción de hacer login y ver los contenidos protegidos por el registro de usuarios, y nada más, no podrán ni crear contenidos y editarlos ni borrarlos.

Si queréis ver más sobre los permisos de usuarios os dejo este enlace en el que están detallados todos los permisos que posee cada tipo de perfil:
http://codex.wordpress.org/Roles_and_Capabilities

También existe un plugin muy útil para aún con los permisos que hemos visto que tienen los usuarios, poder jugar con más características o profundizar más en las capacidades que tendrá cada uno de ellos, yo en concreto lo utilizo mucho para por ejemplo aún siendo Editor del portal un usuario, que este no pueda crear nuevas categorías de post o no tenga acceso a los perfiles del resto de usuarios.
El plugn es Adminimize y aunque en principio pueda parecer que es muy complicado o extenso, si nos fijamos, veremos de forma clara qué es cada uno de los permisos y cómo concederlos o denegarlos, bastará con marcar o no la casilla en la columna del tipo de usuario que deseemos. Un apunte más, si desactivamos los permisos para los usuarios Administradores, estos desaparecerán para los administradores pero no para el SuperAdmin, de esa forma podemos cortar permisos de administradores sin que se pierdan con nuestro usuario SuperAdmin.


Atención, esta información sólo será útil en caso de que tu WP tenga el acceso básico que trae por defecto, si estás usando algún plugin como wp-mylogin o similares, o tu theme ya trae incorporado una interface de login personalizada deberás comprobar que los ajustes se adaptan a tu theme o plugins.

Protección de acceso al sistema
WP tiene dos detalles que corregir en cuanto a seguridad en el acceso al panel de administración o sistema de login, uno, el de protección de ese acceso al sistema, nos indica que por defecto, la información que nos muestra en el panel de login cuando marcamos mal algún dato, ya está indicando qué parte es la que está incorrecta.

A demás no limita de ninguna forma el número de intentos de login que un visitante puede realizar, esto para la protección de ataques por fuerza bruta se puede corregir de forma sencilla instalando y limitando esos accesos con el plugin Login lockdown, una vez instalado y activo podemos configurar estas opciones en Ajustes > Login LockDown.

Esa sería una buena configuración para tener ese bug corregido, el plugin no tiene archivo .po de traducciones y en caso de que algún aviso aparezca en inglés tendremos que traducir esos strings directamente desde el código fuente del archivo: WPContent/Plugns/login-lockdown/loginlockdown.php siempre y cuando tengamos conocimientos de php, el archivo tiene un código bastante sencillo.

Ocultación de ruta de acceso
Otra capa más de seguridad sería la de cambiar la ruta de acceso a nuestro sistema, siempre que está no esté ya personalizada en una url específica, para comprobar esto lo mejor es escribir directamente una de estas dos direcciones url:

http://www.tunombrededominio.es/wp-login http://www.tunombrededominio.es/wp-admin

Si nos carga la página de login del sistema estaremos dando pistas sobre qué tipo de CMS estamos utilizando y qué página es la que tienen el formulario de entrada al panel de administración, ya que las rutas wp-login y wp-admin son conocidas por cualquier atacante que quiera probar si están disponibles.
Lo mejor para corregir esto es cambiar esas direcciones url por una personalizada por nosotros mismos, para ello una vez más utilizaremos la ayuda del plugin gratuito HC Custom WPAdmin URL

Tras instalarlo y activarlo iremos a Ajustes > Enlaces permanentes y en la casilla que pone:

Seguridad en WordPress

Escribiremos el slug para la url de acceso que queramos poner por ejemplo http://www.nombrededominio.es/acceso-seguro de esa forma no se podrá saber qué dirección url es la que da acceso al panel de login del sistema.

Borrar sistema y versión de WordPress de cara al visitante

Por otro lado es mejor que nadie sepa qué versión usamos de WP y si es posible que tampoco sepan ni siquiera que estamos usando WP para trabajar con los contenidos de nuestra página.
Un paso para ocultar estos datos ya lo hemos hecho borrando el archivo readme.html, pero si vemos el código fuente de la página de inicio por ejemplo encontraremos en el apartado <head> del documento dos líneas de código que muestran la versión de WP que se está usando en la página:

Para evitar que se muestren estas metas podemos hacerlo introduciendo código php en el archivo functions.php de nuestro theme, para hacerlo abrimos el archivo NombreDeDominio/wp-content/themes/NombreDeNuestroTheme/functions.php y al final del mismo incluimos estas las siguientes líneas de código:

/*Mis Funciones*/
remove_action('wp_head', 'wp_generator');
remove_action('wp_head', 'woocomerce_generator');
remove_action('wp_head', 'wlwmanifest_link');
remove_action('wp_head', 'rds_link');

Con esto estaremos ocultando las versiones de WP y WooComerce (en caso de que estemos usando ese plugin de comercio electrónico) del código fuente de las páginas de nuestro dominio.


Seguridad en WordPress

Options All -Indexes
User-agent: MSIECrawler
Disallow: /

User-agent: WebCopier
Disallow: /

User-agent: HTTrack
Disallow: /

User-agent: Microsoft.URL.Control
Disallow: /

User-agent: libwww
Disallow: /

User-agent: *
Disallow: /cgi-bin/
Disallow: /wp-content/cache/
Disallow: /wp-content/themes/
Disallow: /comments/
Disallow: /category/*/*
Disallow: */feed/
Disallow: */comments/
Disallow: /*?
Disallow: /wp-content/plugins/
Disallow: /wp-content/themes/
Disallow: /wp-includes/
Disallow: /wp-admin/
Disallow: /?s=
Disallow: /search
Disallow: /wp-
Disallow: /feed/
Disallow: /comments/feed
Disallow: */feed/$
Disallow: */feed/rss/$
Disallow: /trackback/
Disallow: */trackback/ $
Disallow: */*/feed/$
Disallow: */*/feed/rss/$
Disallow: */*/trackback/$
Disallow: */*/*/feed/$
Disallow: */*/*/feed/rss/$
Disallow: */*/*/trackback/$
Allow: /wp-content/uploads/

User-agent: noxtrumbot
Crawl-delay: 50

User-agent: msnbot
Crawl-delay: 30

User-agent: Slurp
Crawl-delay: 10

# Google Image
User-agent: Googlebot-Image
Disallow:
Allow: /*

# Google AdSense
User-agent: Mediapartners-Google*
Disallow:
Allow: /*

# Internet Archiver Wayback Machine
User-agent: ia_archiver
Disallow: /

# digg mirror
User-agent: duggmirror
Disallow: /
# Sitemap permitido, búsquedas no.
Sitemap: http://www.nombrededominio.com/sitemap_index.xml
# Inyecciones sql
Options +FollowSymLinks
RewriteEngine On
RewriteCond %{QUERY_STRING} (\<|%3C).*script.*(\>|%3E) [NC,OR]
RewriteCond %{QUERY_STRING} GLOBALS(=|\[|\%[0-9A-Z]{0,2}) [OR]
RewriteCond %{QUERY_STRING} _REQUEST(=|\[|\%[0-9A-Z]{0,2})
RewriteRule ^(.*)$ index.php [F,L]
RewriteCond %{QUERY_STRING} (;|<|>|'|"|\)|%0A|%0D|%22|%27|%3C|%3E|%00).*(/\*|union|select|insert|cast|set|declare|drop|update|md5|benchmark) [NC,OR]
RewriteCond %{QUERY_STRING} \.\./\.\. [OR]
RewriteCond %{QUERY_STRING} (localhost|loopback|127\.0\.0\.1) [NC,OR]
RewriteCond %{QUERY_STRING} \.[a-z0-9] [NC,OR]
RewriteCond %{QUERY_STRING} (<|>|'|%0A|%0D|%27|%3C|%3E|%00) [NC]
RewriteRule .* - [F]
add_filter('pre_comment_content','wp_specialchars');

Volver a la Portada de Logo Paperblog