Cómo aplicar medidas de seguridad a un sitio web en WordPress mediante el uso del archivo .htaccess. No necesitaremos instalar y configurar plugins, que en muchas ocasiones puede ralentizar la carga de la web. Algunas de las opciones que explicaremos sirven para cualquier sitio web, independientemente de como esté implementado: Joomla!, Drupal, o desarrollos web propios.
- Requisitos y recomendaciones antes de proteger sitio web.
- Desactivar opciones del servidor web de generar ficheros de traza en los errores y avisos.
- Evitar la navegación por directorios.
- Proteger el fichero wp-config.php.
- Desactivar acceso a fichero xmlrpc.php.
- Bloquear acceso a determinadas IP públicas de posibles atacantes.
- Evitar el hotlinking.
- Bloquear acceso de bots maliciosos.
- Proteger el propio fichero .htaccess.
- Evitar acceso a la carpeta wp-content.
- Limitar acceso a administración de WordPress.
- Ejemplo completo de fichero .htaccess del raíz para securizar sitio web con WordPress.
Requisitos y recomendaciones antes de proteger el sitio web
Antes de continuar explicando este proceso, conviene destacar que es más eficiente realizar estas opciones de seguridad en los ficheros de configuración de los sitios web virtualhosts (sites-enabled, sites-availables). Utilizaremos esta opción de .htaccess, que explicamos a continuación, cuando no tengamos acceso a estos ficheros.
En primer lugar, realizaremos una copia de seguridad del archivo .htaccess que, casi siempre, ya existirá en la carpeta raíz de nuestro sitio web. Accederemos o bien mediante conexión SSH con PyTTY (o cualquier otro cliente) o bien mediante FTP, con algún cliente FTP, como Filezilla Client. En este caso, accederemos al sitio web mediante Filezillza.
Una vez conectados, descargaremos el fichero .htaccess que aparecerá en el raíz del sitio web. Lo descargaremos a alguna carpeta de nuestro equipo local, para mantener una copia de seguridad, por si tenemos que volver a su estado inicial. En Filezilla, si no aparece el fichero .htaccess, puede que haya que marcar la opción «Forzar mostrar archivos ocultos», que se encuentra en el menú «Servidor»:
En la parte izquierda, seleccionaremos una carpeta de nuestro equipo, donde se descargará el fichero .htaccess, en la parte izquierda, accederemos a la raíz de nuestro sitio web, donde se encuentra el fichero .htaccess y los ficheros de inicio de la web (como el index.php). Pulsaremos con el botón derecho sobre el fichero .htaccess y en el menú emergente elegiremos «Descargar»:
Guardaremos el fichero descargado en local por si lo necesitáramos para restablecerlo a su configuración original.
En un sitio web con WordPress, tendrá este contenido por defecto:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
# BEGIN WordPress # Las directivas (líneas) entre «BEGIN WordPress» y «END WordPress» son # generadas dinámicamente y solo deberían ser modificadas mediante filtros de WordPress. # Cualquier cambio en las directivas que hay entre esos marcadores serán sobrescritas. <IfModule mod_rewrite.c> RewriteEngine On RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] RewriteBase / RewriteRule ^index\.php$ - [L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /index.php [L] </IfModule> # END WordPress |
Para el proceso de securización que indicaremos a continuación, editaremos el fichero .htaccess de la carpeta raíz (y crearemos algún fichero .htaccess en algunas subcarpetas de WordPress). Para editar el fichero .htaccess, desde Filezilla, pulsaremos con el botón derecho del ratón sobre él y elegiremos «Ver/Editar»:
La primera vez que lo abramos puede que Filezilla nos pregunte con qué programa queremos abrirlo, seleccionaremos el Notepad o cualquier otro editor de texto plano (si estamos en un equipo Windows). Si estamos accediendo mediante SSH y el sitio web lo tenemos sobre Linux, podremos usar vi o nano como editores del fichero.
Nota: en caso de no existir el fichero .htaccess en el raíz del sitio web, lo crearemos, aunque esto no es lo habitual.
El fichero .htaccess, desde Filezilla, se abrirá con el editor elegido (en este caso con Notepad++) y quedará listo para su modificación:
Muy importante: las modificaciones de este fichero las realizaremos SIEMPRE después de la línea «# END WordPress»:
Por supuesto, las medidas de seguridad que explicaremos a continuación no deben ser las únicas, son un refuerzo complementario. Hay otras muchas medidas que se deben aplicar, como por ejemplo montar un WAF (Web Application Firewall) o también medidas a nivel de sistema operativo: actualizado, con EDR, Apache o Nginx bien configurado con todas las medidas de seguridad, el desarrollo, si es propio, debe seguirse según las guías de seguridad específicas, etc..
Desactivar opciones del servidor web de generar ficheros de traza en los errores y avisos
Empezaremos por desactivar las opciones de los servidores web de trace y track, que son ficheros que se generan cuando se producen algún aviso o error y que pueden contener información que un atacante puede usar para hackear nuestro sitio web. Para desactivar el trace y track añadiremos estas líneas al fichero .htaccess del raíz de nuestro sitio web, editándolo como hemos indicado en el punto anterior:
1 2 3 |
# Evitar el trace y track de HTTP RewriteCond %{REQUEST_METHOD} ^(TRACE|TRACK) RewriteRule .* - [F] |
Esta opción de seguridad puede servir para cualquier sitio web, además de WordPress.
Evitar la navegación por directorios
Otra opción que es recomendable desactivar es la navegación por directorios, para evitar que un script o robot pueda acceder a la estructura de carpetas que tengamos en nuestro servidor web. Para ello, en el fichero .htaccess de la carpeta raíz de nuestro sitio web, añadiremos las líneas:
1 2 |
# Evitar navegación por directorios Options All -Indexes |
Esta opción de seguridad puede servir para cualquier sitio web, además de WordPress.
Proteger el fichero wp-config.php
Es recomendable añadir una protección extra al fichero wp-config.php, ya que puede contener, entre otras cosas, usuario y contraseña de acceso a la base de datos. Para ello, en el fichero .htaccess de la carpeta raíz de nuestro sitio web, añadiremos las líneas:
1 2 3 4 5 |
# Proteger fichero wp-config.php <Files wp-config.php> order allow,deny deny from all </Files> |
Desactivar acceso a fichero xmlrpc.php
Salvo que lo usemos expresamente, es recomendable desactivar el acceso al fichero xmlrpc.php de WordPress, que se usa para ejecutar procedimientos remotos y puede resultar inseguro. Para ello, en el fichero .htaccess de la carpeta raíz de nuestro sitio web, añadiremos las líneas:
1 2 3 4 5 |
# Deshabilitar acceso a xmlrpc.php <files xmlrpc.php> order allow,deny deny from all </files> |
Bloquear acceso a determinadas IP públicas de posibles atacantes
Si tenemos algún plugin o algún listado de IP que están intentando acceder contínuamente a la sección de administración de nuestro sitio web y consideramos que puedan ser «maliciosas», podemos bloquer su acceso añadiendo al fichero .htaccess del raíz de nuestro sitio web las siguientes líneas (en este ejemplo, las IP que mostramos son de atacantes reales, de «robots» que han insertado entradas en sitios web WordPress aprovechando alguna vulnerabilidad):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
# Bloquear acceso a IPs <Limit GET POST> order allow,deny deny from 156.195.138.177 deny from 186.167.244.48 deny from 186.167.244.48 deny from 188.126.73.197 deny from 195.246.120.164 deny from 185.217.188.252 deny from 172.111.244.32 deny from 188.126.73.218 deny from 156.195.184.179 deny from 156.195.186.66 allow from all </Limit> |
Esta opción de seguridad puede servir para cualquier sitio web, además de WordPress.
Evitar el hotlinking
Si queremos evitar que otros sitios web enlacen a las imágenes de nuestro sitio web, incluso en esos casos, mostrar una imagen personalizada (para por ejemplo hacer publicidad de nuestro sitio web), añadiremos al fichero .htaccess del raíz de nuestro sitio web las siguientes líneas. Teniendo en cuenta que, si queremos aplicar la desactivación del hotlinking correctamente, procederemos con precaución, porque podríamos bloquear el acceso a las imágenes de nuestro sitio web. Por ello, recomendamos probarlo y si no funciona correctamente, comentar las líneas hasta que consigamos la configuración adecuada:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
# Evitar el hotlinking RewriteCond %{HTTP_REFERER} !^$ RewriteCond %{HTTP_REFERER} !^http(s)?://(www.)?proyectoa.com [NC] RewriteCond %{HTTP_REFERER} !^http(s)?://(www.)?google.com [NC] RewriteCond %{HTTP_REFERER} !^http(s)?://(www.)?google.es [NC] RewriteCond %{HTTP_REFERER} !^http(s)?://(www.)?bing.com [NC] RewriteCond %{HTTP_REFERER} !^http(s)?://(www.)?bing.es [NC] RewriteCond %{HTTP_REFERER} !^http(s)?://(www.)?yahoo.com [NC] RewriteCond %{HTTP_REFERER} !^http(s)?://(www.)?yahoo.es [NC] RewriteCond %{HTTP_REFERER} !^http(s)?://(www.)?threads.net [NC] RewriteCond %{HTTP_REFERER} !^http(s)?://(www.)?facebook.com [NC] RewriteCond %{HTTP_REFERER} !^http(s)?://(www.)?facebook.es [NC] RewriteCond %{HTTP_REFERER} !^http(s)?://(www.)?twitter.com [NC] RewriteCond %{HTTP_REFERER} !^http(s)?://(www.)?wikiloc.com [NC] RewriteCond %{HTTP_REFERER} !^http(s)?://(www.)?strava.com [NC] blogger.com linkedin.com # Imagen que se mostrará en los sitios web en los que nos hagan hotlinking # Debe estar alojada en un sitio web externo al nuestro (para evitar que se bloquee) RewriteRule .(jpg|jpeg|png|gif)$ https://ibb.co/RNHDJwQ [NC,R,L] |
En el ejemplo anterior, hemos permitido las imágenes únicamente desde nuestro sitio web y desde los buscadores Google, Bing y Yahoo. Y hemos añadido una última línea para que si algún sitio web externo enlaza a alguna de nuestras imágenes, aparezca una publicada por nosotros en un sitio web externo, en este ejemplo aparecerá:
Añadiremos los sitios webs externos a los que sí permitamos el hotlinks, como redes sociales: Facebook, Twitter, LinkedIn, Threads, Wikiloc, Strava.
Esta opción de seguridad puede servir para cualquier sitio web, además de WordPress.
Bloquear acceso de bots maliciosos
Existen multitud de bots que tienen programas para acceso a sitios webs, para extraer información para diversos fines ilícitos (spam, minería de datos, scrapping, etc.). Es recomendable bloquear el acceso a estos bots automáticos, dado que también influyen en el rendimiento de la web. Para ello, editaremos el fichero .htaccess del raíz de nuestro sitio web y añadiremos estas líneas:
1 2 3 4 5 6 |
# Bloquear bots maliciosos SetEnvIfNoCase User-Agent "BannedBot" bad_bot SetEnvIfNoCase User-Agent "EvilBot" bad_bot Order Allow,Deny Allow from all Deny from env=bad_bot |
Vigilaremos siempre que estas líneas no impidan el acceso de los bots lícitos, como los buscadores Google, Yahoo, Bing u otros. Para ello, revisaremos las cachés de búsqueda de nuestro sitio web en dichos buscadores y revisaremos que la fecha de escaneo sea reciente.
Esta opción de seguridad puede servir para cualquier sitio web, además de WordPress.
Evitar ataques de inyección de SQL
En la medida de lo posible, porque no se trata de un WAF, podremos evitar algunos de los ataques típicos de inyección de SQL y de XSS Cross Site Scripting, añadiendo estas líneas al fichero .htaccess del raíz de nuestro sitio web:
1 2 3 4 5 6 7 |
# Evitar ataques de inyección 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] |
Proteger el propio fichero .htaccess
Por supuesto, cada vez que creemos un fichero .htaccess, es muy recomendable aplicarle una protección extra. Si un atacante accede a este fichero, podría modificar y desactivar las opciones de seguridad anteriores y aplicar otras opciones para reducir la seguridad. Para ello, en el fichero .htaccess de la carpeta raíz de nuestro sitio web, añadiremos las líneas:
1 2 3 4 5 |
# Proteger el propio .htaccess <Files .htaccess> order allow,deny deny from all </Files> |
Esta opción de seguridad puede servir para cualquier sitio web, además de WordPress.
Evitar acceso a la carpeta wp-content
Otra opción para reforzar la seguridad y evitar ataques, es proteger la carpeta wp-content de WordPress. Para ello, crearemos (si no existe) un fichero .htaccess dentro de la carpeta wp-content de WordPress:
Y le añadiremos el siguiente contenido:
1 2 3 4 5 |
Order deny,allow Deny from all <Files ~ ".(xml|css|jpe?g|png|gif|js|svg|ico|bmp|mo|po|ttf|woff)$"> Allow from all </Files> |
Procederemos con precaución con este método de protección. En nuestro caso, al aplicarlo, no aparecían algunos iconos del sitio web, hubo que añadir las extensiones: ico, ttf, woff, mo y po.
Esta opción de seguridad puede servir para cualquier sitio web, además de WordPress, modificando las extensiones a permitir y colocando el fichero .htaccess en la carpeta a la que queramos dar protección adicional.
Limitar acceso a la administración de WordPress
Si disponemos de IP pública fija (estática), también es muy recomendable limitar el acceso a la administración de WordPress y sólo permitir que accedan equipos con la IP estática indicada (pueden ser varias, repitiendo la línea «allow from …». Para ello, crearemos (si no existe) un fichero .htaccess en la carpeta wp-admin de nuestro sitio web WordPress:
1 2 3 |
order deny,allow allow from 111.111.111.111 deny from all |
Cambiaremos 111.111.111.111 por la IP pública con la que salgamos a Internet. Solo desde equipos de esta red podremos acceder a la gestión de WordPress.
Ejemplo completo de fichero .htaccess del raíz para securizar sitio web con WordPress
El contenido de ejemplo de un fichero .htaccess completo para aumentar la protección y seguridad para un sitio web en WordPress podría ser:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
<IfModule mod_security2.c> SecRuleRemoveById 223 225170 101 </IfModule> # BEGIN WordPress # Las directivas (líneas) entre «BEGIN WordPress» y «END WordPress» son # generadas dinámicamente y solo deberían ser modificadas mediante filtros de WordPress. # Cualquier cambio en las directivas que hay entre esos marcadores serán sobrescritas. <IfModule mod_rewrite.c> RewriteEngine On RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] RewriteBase / RewriteRule ^index\.php$ - [L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /index.php [L] </IfModule> # END WordPress # BEGIN GZIP <ifmodule mod_deflate.c> AddOutputFilterByType DEFLATE text/text text/html text/plain text/xml text/css application/x-javascript application/javascript </ifmodule> # END GZIP # BEGIN SEGURIDAD RewriteEngine On # Evitar el trace y track de HTTP RewriteCond %{REQUEST_METHOD} ^(TRACE|TRACK) RewriteRule .* - [F] # Evitar navegación por directorios Options All -Indexes # Evitar el hotlinking # RewriteCond %{HTTP_REFERER} !^$ # RewriteCond %{HTTP_REFERER} !^http://(www.)?proyectoa.com/.*$ [NC] # RewriteRule .(gif|jpg)$ http://www.proyectoa.com/hotlink.gif [R,L] # Evitar spam en comentarios RewriteCond %{REQUEST_METHOD} POST RewriteCond %{REQUEST_URI} .wp-comments-post.php* RewriteCond %{HTTP_REFERER} !.*proyectoa.com.* [OR] RewriteCond %{HTTP_USER_AGENT} ^$ RewriteRule (.*) ^https://%{REMOTE_ADDR}/$ [R=301,L] # Proteger fichero wp-config.php <Files wp-config.php> order allow,deny deny from all </Files> # Deshabilitar acceso a xmlrpc.php <files xmlrpc.php> order allow,deny deny from all </files> # Proteger el propio .htaccess <Files .htaccess> order allow,deny deny from all </Files> # Bloquear acceso a IPs <Limit GET POST> order allow,deny deny from 156.195.138.177 deny from 186.167.244.48 deny from 186.167.244.48 deny from 188.126.73.197 deny from 195.246.120.164 deny from 185.217.188.252 deny from 172.111.244.32 deny from 188.126.73.218 deny from 156.195.184.179 deny from 156.195.186.66 allow from all </Limit> # Bloquear bots maliciosos SetEnvIfNoCase User-Agent "BannedBot" bad_bot SetEnvIfNoCase User-Agent "EvilBot" bad_bot Order Allow,Deny Allow from all Deny from env=bad_bot # Evitar ataques de inyección 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] # END SEGURIDAD |