Configuración de WordPress para mejorar seguridad

Últimamente no dejo de hacer WordPress cada dos por tres, y es muy habitual que se repitan siempre los mismos problemas de unos a otros. He decidido redactar este artículo con los principales pasos que yo estoy siguiendo en mis proyectos para que WordPress tenga la mayor seguridad posible y de menos problemas de configuración.

wp_secure

Previo a la instalación

El truco del directorio

Consiste en instalar tu copia de WordPress en un subdirectorio de tu servidor. De este modo será un poco más complicado el acceder a la zona de administración, ya que deberás de conocer el nombre que has puesto a este subdirectorio. Estos son los pasos que hay que seguir para que todo funcione a la perfección.

  • Copiar la carpeta WordPress en una subcarpeta de tu servidor (no en la raíz)
  • Renombrar por un nombre más especial (que no sea wordpress)
  • Esta subcarpeta no se verá, salvo cuando entres en la administración, lo que hará más difícil a los hackers llegar a los ficheros de tu web.
    • El acceso a admin sera: tudominio.com/tudirectorio/wp-admin
  • Los archivos index.php y .htaccess (si existe) deben ser duplicados en la raíz (no movidos, duplicados)
  • Editar el index.php de la raíz y reemplazar esta línea por la dirección correcta:
    • require(‘./wp-blog-header.php’);
    • debe ser algo asi: require(‘./your_folder/wp-blog-header.php’);
  • La configuración desde los ajustes generales, dentro de la administración
    • Dirección de WordPress (URL) la dirección de la carpeta donde se ha instalado WordPress
    • Dirección del sitio: la raíz

Nota: Yo últimamente vengo aplicando este consejo, que aprendi en este artículo y en este otro artículo, pero dudo que sea realmente efectivo, ya que se puede obtener fácilmente el nombre del subdirectorio elegido viendo la ruta de cualquier imagen de nuestro wordpress.

Base de Datos

A la hora de crear nuestra nueva base de datos conviene tener en cuenta estos dos consejos:

  • Creo la base de datos con el collate: utf8_general_ci
  • Crea un usuario único para esa base de datos (esto protegerá tus otras bases de datos en caso de ataque)

Correcta configuración de wp-config.php

Este fichero variará si estamos usando un Multi Site o no, pero en líneas generales podemos seguir estos pasos para mejorar un poco nuestros WordPress:

  • definir el mismo collate que hemos usado para nuestra base de datos:

define(‘DB_COLLATE’, ‘utf8_general_ci’);

  • Crear unas keys aleatorias desde: https://api.wordpress.org/secret-key/1.1/salt/
  • Cambiar el prefijo de las tablas. Usar el prefijo que viene por defecto (wp_) hace que nuestras tablas sean menos seguras.
  • No permitir edición de ficheros php desde la administración:

define(‘DISALLOW_FILE_EDIT’, true);

  • Prohibir instalación de temas y plugins desde la administración. Solo podrán ser instalados desde el FTP

define(‘DISALLOW_FILE_MODS’,true)

  • Una vez instalado mover el fichero wp-config.php al directorio superior de la instalación de wordpress
  • Mientras estamos desarrollando tener el modo WP_DEBUG a true (acordaros de quitarlo cuando termineis de desarrollar)
  • Si el servidor acepta SSL añadir esta línea en el wp-config.php:

define(‘FORCE_SSL_ADMIN’, true);

Nombre de usuario y clave

  • Usar un nombre de usuario que no sea “admin”
  • Es evidente, pero hay que decirlo: Usar contraseñas seguras y únicas

Permisos carpetas

Nos podremos evitar muchos de los dolores de cabeza que nos puede provocar WordPress si establecemos los permisos correctos en directorios y ficheros.

  • Todos los ficheros deben pertenecer a tu usuario (normalmente el mismo usuario que usas para conectar por FTP) y ser escribibles por este.
  • Por defecto los directorios tendrán permisos 755 y los archivos 644
  • Ficheros wp-config.php y .htaccess: 0644 o para paranoicos 0444
  • directorios:
    • /wp-admin/: debe ser escribible solo por tu usario. (755)
    • /wp-includes/: debe ser escribible solo por tu usuario. (755)
    • /wp-content/:
      • /wp-content/themes/: escribible solo por tu usuario (esto hará que no se pueda usar el editor en línea de la administración) 755
      • /wp-content/plugins/: escribibles solo por tu usuario (755)
      • /wp-content/uploads/: debe pertenecer al grupo usado por el servidor, para que WordPress pueda crear los nuevos ficheros subidos.

Permisos especiales para plugins

Algunos plugins necesitan de cuidados especiales para su correcto funcionamiento. Aquí os explico alguno de estos casos.

  • Si se usa el timthumb.php (sistema de redimensionado de imagenes):
    • Asignar permisos 777 a la carpeta /cache situada en el mismo directorio que timthumb.php
    • También necesita que el servidor tenga instalada la librería GD image
    • si hay problemas puede que estos trucos te ayuden
  • Si usas el plugin de Better WP Minify cambia los permisos de la carpeta cache (mira en la configuración del plugin cual es la carpeta) CHMOD a 755 o 777.
  • Si usas el plugin de WP Super Cache cambia los permisos de la carpeta cache (mira en la configuración del plugin cual es la carpeta) CHMOD a 755 o 777. Aquí explica como configurarlo

.htaccess a prueba de balas

Mucha de “la magia” que hace WordPress es gracias al fichero .htaccess que debemos tener en la raíz de nuestra instalación. Aquí os cuento cual uso yo: # establece la url canonica (amigable) RewriteEngine On RewriteCond %{HTTP_HOST} ^tudominio\.com$ [NC] RewriteRule ^(.*)$ [R=301,L]

# protege el archivo wp-config.php
 <Files wp-config.php>
 order allow,deny
 deny from all
 </Files>
# protege el archivo htaccess
 <files .htaccess>
 order allow,deny
 deny from all
 </files>
 # protección extrema de htaccess
 <Files ~ "^.*\.([Hh][Tt][Aa])">
 order allow,deny
 deny from all
 satisfy all
 </Files>
# desactiva la firma del servidor
 ServerSignature Off
# limita la carga de archivos a 10mb
 LimitRequestBody 10240000
# desactiva la navegacion de directorios
 Options All -Indexes
# protege el directorio wp-includes
 # Block the include-only files.
 RewriteEngine On
 RewriteBase /
 RewriteRule ^wp-admin/includes/ - [F,L]
 RewriteRule !^wp-includes/ - [S=3]
 RewriteRule ^wp-includes/[^/]+\.php$ - [F,L]
 RewriteRule ^wp-includes/js/tinymce/langs/.+\.php - [F,L]
 RewriteRule ^wp-includes/theme-compat/ - [F,L]
# protege de comentarios spam
 <IfModule mod_rewrite.c>
 RewriteEngine On
 RewriteCond %{REQUEST_METHOD} POST
 RewriteCond %{REQUEST_URI} .wp-comments-post\.php*
 RewriteCond %{HTTP_REFERER} !.*yourdomainname.* [OR]
 RewriteCond %{HTTP_USER_AGENT} ^$
 RewriteRule (.*) ^http://%{REMOTE_ADDR}/$ [R=301,L]
 </IfModule>
 # evitar inyección de codigo por SQL
 # leido en: http://wwwhatsnew.com/2013/04/05/guia-de-seguridad-en-wordpress-iii/
 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]

Otros .htaccess que debemos crear

Proteger el directorio uploads. Crear este .htaccess dentro del directorio wp-content/uploads

 # Protege el directorio uploads
 <Files ~ ".*..*">
 Order Allow,Deny
 Deny from all
 </Files>
 <FilesMatch ".(jpg|jpeg|jpe|gif|png|tif|tiff|pdf)$">
 Order Deny,Allow
 Allow from all
 </FilesMatch>

Configuración de otros plugins

Redirections

No marcar la opción de redirigir los post cuando cambian de slug. La opción mola, pero nos ha dado muchos problemas

WP Super Cache

Aquí os dejo un artículo detallado de como configurar el plugin WP Super Cache

Numero de intentos

  • Definir un límite de intentos de acceso antes de deshabilitar una cuenta por una hora en ejemplo, por lo que un atacante necesitará una cantidad muchísimo mayor de tiempo para descubrir la contraseña.
  • Hay Plugins que permiten el cambio de la URL de acceso como Hide Login, que de hecho permite crear una URL personalizada para facilitar la memorización de la misma mientras se dificulta el acceso de terceros.

Últimos pasos

  • Siempre que sea posible debemos de conectarnos a nuestra máquina a través de SFTP. Es mucho más seguro que el FTP.
  • Configurar Backups. Tanto con el proveedor de hosting como con plugins como WordPress Database Backup que te mandan periódicamente copias de la base de datos a tu email.
  • Instalar el plugin WP – Security para solventar algunos posibles problemas de seguridad
  • Borrar todos los themes y plugins que no se usen. Aunque no los tengamos instalados puede ser agujeros de seguridad.
  • Comprueba que todo funciona desde fuera de tu red (a veces hay cosas que están configuradas para que solo sean visibles desde dentro de tu ordenador)

Puntos a revisar cuando termines la web

  • Reemplazar en la base de datos todos los http://localhost… por http://servidordepro…
  • Comprobar que los custom links de los menús apunten al dominio correcto.
  • Poner el modo WP_DEBUG a false en el wp-config.php
  • Permalinks
  • Si es multisite:
    • ver que funciona la navegación de cada site
    • Acceder a la administración de cada site
    • Comprobar links entre post/paginas traducidas
  • Envío de formularios: Tanto al receptor como al emisor
  • Registro en el newsletter:
    • con el formulario de newsletter
    • con formularios de contacto (candidatura)
  • Si usas TimThumb: Asegurarse que crea nuevas imágenes.
    • Hay que añadir el dominio correspondiente en $ALLOWED_SITES, en el fichero timthumb.php
  • Responsive CSS. Prueba a redimensionar tu navegador, y visita la web con tu móvil o tableta.
  • Social
    • Compartir pagina/post
    • Links a twitter, facebook corporativos. Que se muestren bien
  • SEO
    • Que muestre bien las metaetiquetas
    • Que muestre bien el título
    • Que no haya un robots.txt bloqueando el acceso

Mantenimiento

Cuando haya que hacer cambios en un WordPress en producción se deberá de poner un “telón” para que las personas que visiten la web mientras el mantenimiento no puedan ver la web.

Añadir este código en function.php, leído aquí.

function wpr_maintenance_mode() {
if ( !current_user_can( 'edit_themes' ) || !is_user_logged_in() ) {
wp_die(‘Maintenance, please come back soon.’, ‘Your Website Name’);
}
}
add_action('get_header', 'wpr_maintenance_mode');

También se puede hacer esto mismo con el plugin WP Maintenance Mode.

Otros problemas que he tenido

Problema con el wp-cron.php

Por alguna razón cada X minutos al refrescar la pagina me da este problema:

Warning: fopen(http://server/wp-cron.php?doing_wp_cron=1367....): failed to open stream: HTTP request failed! in /var/www/wordpress/wp-includes/class-http.php on line 921

Siguiendo las instrucciones de este foro, he procedido a instalar curl en el servidor:

sudo apt-get install php5-curl

Al parecer es un problema con el servidor que yo uso que corre en Windows. Cuando lo pongo en un servidor linux todo va bien.

Actualizar el número de comentarios en las entradas

Si has importado tus posts de otro wordpress, puede que el número de comentarios que te aparece en un post no coincida con la realidad.

Si este es tu caso, puedes seguir los pasos que indican en este artículo.

UPDATE wordpress.wp_posts wpp
LEFT JOIN
(SELECT comment_post_id AS c_post_id, count(*) AS cnt
FROM wordpress.wp_comments
WHERE comment_approved = 1 GROUP BY comment_post_id) wpc
ON wpp.id=wpc.c_post_id
SET wpp.comment_count=wpc.cnt
WHERE wpp.post_type IN ('post', 'page')
AND (wpp.comment_count!=wpc.cnt
OR (wpp.comment_count != 0 AND wpc.cnt IS NULL));

Nota: Recuerda cambiar el prefijo de las tablas SQL por el tuyo.

Hasta aquí puedo leer…

Espero que parte de mi experiencia con WordPress os sea de ayuda. Si veis cualquier error, o se os ocurre añadir cualquier otro truco, no dudéis en poner un comentario a este artículo.