Como instalar WordPress de forma más segura

Foto de David M. Goehring

Aviso: este artículo esta pensado para aquellos que tengan su propio servidor. Si no tienes acceso de administrador, ni puedes configurar apache a tu antojo, la utilidad de esto es limitada (aunque puedes encontrar algún consejo interesante)

Hace un tiempo, me cansé de los problemas de seguridad con mi instalación de WordPress. Mantengo varios blogs, y a menudo eran víctimas de ataques. La razón principal es que es costoso mantenerlos actualizados si no se utiliza la actualización automática.

Para que la actualización automática de WordPress pueda funcionar hay dos opciones:

  1. Que apache tenga permisos de escritura sobre todo el árbol de WordPress
  2. Usar FTP, o SSH

La primera opción creaba más problemas de los que solucionaba, y la segunda requería una cierta configuración en el servidor: tener un servidor de FTP, o instalar la extensión de PHP para usar ssh.

Paso 0: migrar de servidor

En realidad no es necesario. En mi caso, y tras encontrar múltiples puertas traseras en mi antiguo servidor, decidí empezar de cero. Instalé versiones limpias de WordPress e importé el contenido y los temas con cuidado (mucho menos costoso que revisar todos los archivos). También aproveché para cambiar todas las contraseñas: no podía estar seguro de que no estuvieran comprometidas.

Además, el momento decisivo fue cuando descubrí que Linode, mi proveedor de hosting, ahora ofrecía alojamiento en Europa (Londres).

Paso 1: organización de wordpress y permisos

La forma más segura de instalar wordpress (en cuestión de permisos) es no permitir que el servidor web pueda escribir en ningún sitio. Esto no es práctico, ya que nos deja sin poder subir ficheros, actualizar wordpress, y otras comodidades. Habrá que encontrar un punto medio.

En lugar de tener wordpress en un solo directorio, separo el fichero wp-config.php y el directorio wp-content. Esto no ofrece una mayor seguridad, pero facilita las actualizaciones manuales, y la revisión de posibles infecciones.

Pongamos como ejemplo:

  • /srv/www/ejemplo.com – directorio base
  • /srv/www/ejemplo.com/htdocs – instalación de wordpress
  • /srv/www/ejemplo.com/wp-config.php – fichero de configuración
  • /srv/www/ejemplo.com/wp-content – datos de wordpress

Para asegurarnos el buen funcionamiento, enlazamos wp-content y wp-config.php dentro de htdocs. El proceso para instalar un nuevo blog sería algo así:

cd /srv/www
wget http://wordpress.org/latest.tar.gz
tar zxvf latest.tar.gz
rm latest.tar.gz
mv wordpress htdocs
mv htdocs/wp-content .
cp htdocs/wp-config-sample.php wp-config.php
cd htdocs
ln -s ../wp-config.php wp-config.php
ln -s ../wp-content wp-content

Ahora queda cambiar los permisos. Supongamos que nuestro usuario en el sistema es usuario y el usuario con el que se ejecuta apache es www-data.

chown -R usuario /srv/www/ejemplo.com
chown -R www-data /srv/www/ejemplo.com/wp-content/uploads

Sólo necesitamos que apache pueda escribir en el directorio donde se suben los adjuntos. Para las actualizaciones usaremos FTP con nuestro usuario.

Paso 2: configuración de WordPress


<?php
// ** MySQL settings ** //
define('DB_NAME', '****');    // The name of the database
define('DB_USER', '****');     // Your MySQL username
define('DB_PASSWORD', '****'); // ...and password
define('DB_HOST', 'localhost');    // 99% chance you won't need to change this value

$table_prefix  = 'xxx_'; // No usar wp_ evita muchos de los exploits automáticos
define('WP_SITEURL','http://www.ejemplo.com');
define('WP_HOME','http://www.ejemplo.com');
define('WP_CONTENT_DIR', '/srv/www/ejemplo.com/wp-content' );
define('WP_CONTENT_URL', 'http://www.ejemplo.com/wp-content');

define('FORCE_SSL_LOGIN', true);
define('FORCE_SSL_ADMIN', true);

// Entramos en http://api.wordpress.org/secret-key/1.1/ y generamos unas nuevas
define('AUTH_KEY',        't3j$Fk<4BOt=^}SK-GnunxGYNx:6Le|HYEw06O0Lu,9rLm/SMOl2-6h2iItw.tf(');
define('SECURE_AUTH_KEY', '9QQNc;namb%I|xpv*g~7)1ci5X.z9hc3./J-SyT{V64NC I~*W_T+Y<|TT@n&Zs+');
define('LOGGED_IN_KEY',   '=G*+; 4=u%41e]o;)#V/|-v8Y=.ilK1sO6S(!n4z/M0rE(UYhd[_z*HNhjDSp}YR');
define('NONCE_KEY',       '8aUPH}vy$mb,3As}aZY)Lmr_2Qw|B6mb8ivV[!(h7T3$0ENpVLvABhkK0s<IOxel');

// Si queremos wordpress en español. Habrá que instalar también la traducción
define ('WPLANG', 'es_ES');

/* That's all, stop editing! Happy blogging. */

//define('ABSPATH', dirname(__FILE__).'/');
define('ABSPATH', '/srv/www/ejemplo.com/htdocs/');
require_once(ABSPATH.'wp-settings.php');
?>

Revisemos algunos de los parámetros:

  • FORCE_SSL_LOGIN: Fuerza que los usuarios se identifiquen mediante conexión segura
  • FORCE_SSL_ADMIN: Todo el panel de administración funciona mediante conexión segura

Como vamos a usar FTP para las actualizaciones, no queremos que cuando wordpress nos pregunte nuestra contraseña se transmita sin cifrar. Por eso restringimos todo el panel de administración, y no solo el login.

Por supuesto, esto requiere configurar apache para que pueda servir nuestro blog de forma segura, pero eso queda ya para otro artículo.

También necesitamos un servidor de FTP funcionando. En mi caso instalé vsftpd sin mucha complicación.

¿Paso 4?

¿Tienes algún truco para hacer wordpress más seguro? ¿Algún plugin? Cuéntanoslo en un comentario.

Cómo usar una imagen de fondo que se adapte a la pantalla

Actualizado 23-Sep: Arreglado fallo en IE8

Hace unos meses, estuve trabajando en la web de Amapola Films, y surgió un reto interesante: cómo usar una imagen de fondo que permaneciese fija y tuviera una escala correcta.

Para este ejemplo, he elegido la siguiente imagen de fondo:

La imagen de fondo que usaremos de ejemplo

Prueba #1: usando CSS

Normalmente, para poner una imagen de fondo usaría CSS, pero en este caso queremos que ocupe toda la pantalla independientemente del tamaño del navegador.

He reducido la página al mínimo para poder centrarnos en el fondo, así que el contenido del body sería:

<div id="content">
<h1>Prueba 1: usando CSS</h1>
</div>

Y el CSS correspondiente:

body {
  background: url(images/background.jpg) no-repeat center top;
}

Como se puede ver en la siguiente captura, la imagen es mucho más grande que la ventana del navegador y no se muestra correctamente

Primer intento: FAIL

La propiedad background de CSS es bastante limitada para este caso y  no nos permite escalar la imagen. Si queremos ajustar la anchura o altura, tendremos que usar el elemento img

Prueba #2: imagen en HTML

Esta vez, en lugar de ponerle un fondo al body, vamos a insertar una imagen en el documento e intentar enviarla al fondo.

<img id="bg" src="images/background.jpg" alt="Fondo" />
<div id="content">
<h1>Prueba 2: imagen de fondo</h1>
</div>

Para esto, aplicaremos un posicionado fijo a la imagen, y le pondremos el z-index a -1, para enviarla al fondo. También especificamos que la imagen se ajuste al ancho de la pantalla

#bg {
  position: fixed;
  z-index: -1;
  top: 0;
  left: 0;
  width: 100%;
}

Segundo intento, parece que funciona

Con un navegador apaisado se ve decente

El problema viene a la hora de redimensionar. Si por cualquier motivo, la ventana es mas ancha que larga se produce el siguiente efecto.

Segundo intento: FAIL

Tras ver esto, se me ocurrió brevemente poner también la altura al 100%, pero eso deformaría la imagen. Sólo nos queda Javascript

Prueba 3: Javascript al rescate

La idea principal es averiguar mediante javascript las proporciones de la pantalla y, dependiendo de estas, ajustar la anchura o la altura, dejando que el navegador elija la otra medida automáticamente.

El código HTML y CSS es similar al anterior, sólo que esta vez añadiremos el siguiente Javascript (depende de jQuery aunque se podría adaptar fácilmente):

function updateBackground() {
screenWidth = $(window).width();
screenHeight = $(window).height();
var bg = jQuery("#bg");

// Proporcion horizontal/vertical. En este caso la imagen es cuadrada
ratio = 1;

if (screenWidth/screenHeight > ratio) {
$(bg).height("auto");
$(bg).width("100%");
} else {
$(bg).width("auto");
$(bg).height("100%");
}

// Si a la imagen le sobra anchura, la centramos a mano
if ($(bg).width() > 0) {
$(bg).css('left', (screenWidth - $(bg).width()) / 2);
}
}
$(document).ready(function() {
// Actualizamos el fondo al cargar la pagina
updateBackground();
$(window).bind("resize", function() {
// Y tambien cada vez que se redimensione el navegador
updateBackground();
});
});

Podemos ver que en este caso, el fondo se muestra correctamente sea cual sea el tamaño de la ventana.

Cuadrado: OK

Horizontal: OK

Vertical: OK

Demo

Podéis ver los ficheros utilizados en: