Seguridad en WordPress

Base de datos

Antes de iniciar la instalación de WordPress debes crear un usuario único para él, puede sonar obvio para algunos y en realidad lo es: Nunca uses el usuario root de MySQL para conectarlo con tu sitio web. El nuevo usuario no debe necesariamente tener todos los privilegios (ALL PRIVILEGES), con los permisos Create, Delete, Drop, Update, Select, Alter y Execute debería ser suficiente para funcionar, verifica que así lo sea o agrega los que necesites.

crear_usuario_wordpress

Estableciendo permisos para el nuevo usuario en PHPMyAdmin

En el proceso de instalación cambia el prefijo de tabla “wp_” por el que tú quieras.

Directorios

Renombrar directorios

WordPress usa directorios con nombres específicos que pueden ser renombrados, incluso existen como plugins como Better WP SecurityHide My WP para cambiar toda la estructura por defecto y así “ocultar” cuál es el CMS que estamos usando, un poco exagerado pero puede ser útil dependiendo del caso. Para renombrar las carpetas manualmente deberemos agregar lo siguiente al archivo wp-config.php:

// Cambiando el directorio wp-content por "file"
define( 'WP_CONTENT_DIR', dirname(__FILE__) . '/files' );
// Se define la nueva URL con el directorio
define( 'WP_CONTENT_URL', 'http://miweb.trin/files' );
// Cambiando el directorio plugins por "scriptsquemlan"
define( 'WP_PLUGIN_DIR', dirname(__FILE__) . '/files/scriptsquemolan' );
// Definiendo URL de la carpeta plugins
define( 'WP_PLUGIN_URL', 'http://miweb.trin/files/scriptsquemolan' );
// Cambiando el directorio uploads
define( 'UPLOADS', '/files/misfoticos' );

Directorios sin index

Otro asunto importante son los directorios que no tienen index y se listan todos los archivos que contienen, para que no suceda esto en el archivo donde creaste el VirtualHost de Apache para tu sitio debes agregar:

Options -Indexes FollowSymLinks MultiViews

Si no entiendes lo que digo más arriba o tienes un hosting compartido simplemente agrégalo al archivo .htaccess de la raíz. Esto lo que hará es devolver un error 403 en las carpetas sin index, no olvides también agregar un ErrorDocument 403 /index.php para que WP se encargue de “estilizar” el error cuando se muestre, también podríamos mostrar un mensaje personalizado amenazando al visitante… pero somos gente adulta ¿verdad?

Permisos de directorios y archivos

Los archivos utilizados por WordPress deben tener los permisos 644 y los directorios 755, para este punto sólo es poner un poco de lógica de qué permisos poner a X o Y directorio. Básicamente la carpeta wp-content (uploads y plugins) debe tener permisos para poder ser escrita en ella. Por ejemplo si el archivo wp-settings.php no tiene los permisos correctos y además la visualización de errores de PHP está activa verás algo horrible como esto:

errores_wp-settings

Temas y pluginsmeta_version_wordpress

También si eres uno de esos tacaños de mierda que sólo usa themes nulled lo mejor es que sí o sí revises el código, puede que haya alguna sorpresa por ahí.

Cuando se activa un theme es recomendado hurgar un poco en su código en busca de vulnerabilidades o de malas prácticas, es posible que el desarrollador se haya equivocado a la hora de utilizar una función y nos esté provocando un full path disclosure… me sucedió en una ocasión.

Algunos desarrolladores aman estar poniendo versiones y nombres para que sean mostrados en el HTML del sitio, en tal caso de que existiera una vulnerabilidad para la versión especifica que tenemos del theme o plugin los script kiddies nos encontrarían rápido. Para evitar esto algunas personas borran cualquier rastro del theme, por ejemplo eliminando la información que se encuentra en style.css.

theme_info_styleDeberías también agregar lo siguiente al functions.php del tema para que elimine la etiqueta meta con la versión de WordPress y otras cosas más:

if (!is_admin()) {
remove_action( 'wp_head', 'feed_links_extra');
remove_action( 'wp_head', 'feed_links');
remove_action( 'wp_head', 'rsd_link');
remove_action( 'wp_head', 'wlwmanifest_link' );
remove_action( 'wp_head', 'index_rel_link' );
remove_action( 'wp_head', 'parent_post_rel_link', 10);
remove_action( 'wp_head', 'start_post_rel_link', 10);
remove_action( 'wp_head', 'adjacent_posts_rel_link_wp_head', 10);
remove_action( 'wp_head', 'wp_generator');
}

Formulario de acceso y usuarios

evitar_brute_force_wordpress

En cuanto al formulario de acceso si quieres y crees conveniente cambia el directorio wp-admin. Instala el plugin Login LockDown para evitar un ataque por fuerza bruta. Instala WordPress HTTPS (SSL) si tu paranoia te lo dicta.

Usuarios

Por una parte si tienes un sitio con un sólo usuario (o más de uno pero tienen poca actividad los otros) se recomienda por SEO ocultar la página de autor, porque aparecería exactamente lo mismo que en el home, es innecesario. Hablando directamente de seguridad también nos provee un problema enlazar los autores, normalmente la página del autor se generá así: sitio.trin/author/usuario, estaríamos dando fácilmente el usuario y si no tenemos el formulario de acceso protegido… ya te imaginarás.

Sitios con Buddypress o similares

Si usas tu WordPress con registro de usuarios, con un foro y demás cosas que provee Buddypress por ejemplo, entonces deberías agregar lo siguiente a tu functions.php:

add_action('init','restringir_acceso');

function restringir_acceso(){
if (strpos(strtolower($_SERVER['REQUEST_URI']),'/wp-admin/') !== false) {
    if ( !is_super_admin() &&!ajax_request() ) {
      wp_redirect( get_option('siteurl'), 302 );
    }
  }

}
function ajax_request(){
  if (defined('DOING_AJAX') && DOING_AJAX) return true;
    if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest')
        return true;
    return false;
}

El código de arriba lo que hace es que cualquier usuario que no tenga los privilegios suficientes y que intente acceder al panel de administración sea redirigido al inicio del sitio, así nos evitamos fisgones. Por otra parte algunos plugins que hacen peticiones por medio de Ajax necesitan tener acceso, para ello se utiliza la función ajax_request().

Utilizar caché

Sí, es más una recomendación de optimización de lo que puede ser de seguridad. Pero podrás hacerle la vida un poco infeliz a alguien que te quiera tumbar el sitio con algún script que se descargó de Internet, además de eso si activas la minificación de HTML, CSS y Javascript te ahorrarás el trabajo de estar borrando los comentarios de plugins y themes ya que eso se hará automáticamente. Yo utilizo W3 Total Cache (puedes combinarlo con CludFlare por ejemplo), pero puedes encontrar otros más.

Recomendaciones obvias

Ya deberías saberlo, pero aquí van:

  • Realizar backups periodicamente
  • Mantén actualizado los plugins y el WordPress
  • Si es que usas un usuario llamado “admin” con ID 1, renómbralo
  • Elimina los archivos readme.html, license.txt…
  • Cambia el prefijo “wp_” en caso de que lo estés usando
  • Utiliza Akismet para evitar spam y captcha para formulario de contacto o similares
  • ¿Cuál se me escapa?

Artículo en actualización…

  6 Comentarios

  1. Castiblanco   •  

    Útil información… Parce para hacer los backups qué método recomienda?

    • Brian Urban   •     Autor

      6 meses después… xD Personalmente utilizo un script que se ejecuta con cron todos los días a determinada hora y se envía el backup a un servicio en la nube. Otra opción para servidores compartidos podría ser BackUpWordPress.

  2. Mr. Black   •  

    Excelentes pasos 😀 PD: Soy de aquellos tacaños de mierda, tendre que mirar aquel codigo 🙁

    • Brian Urban   •     Autor

      Gracias Mr. Black, no estaría mal de vez en cuando ayudar a los desarrolladores pagando un theme/plugin 😛

      PD: Esta noche doy serrucho.

  3. santiago   •  

    Parse, excelentes tips.
    gracias por compartir

    • Brian Urban   •     Autor

      Saludos viejo Exactlimon, gracias por pasaros por el blogsito.

Deja un comentario

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