Bastionado

wp-config.php: los ajustes de seguridad que de verdad importan

wp-config.php, los ajustes de seguridad que importan

El archivo wp-config.php contiene los datos de acceso a la base de datos y los secretos que firman tus sesiones. Algunas constantes refuerzan claramente un sitio WordPress; otras, mal entendidas, desactivan protecciones sin avisar. Esto es lo que hace realmente cada ajuste, comprobado en el código fuente actual de WordPress, y la configuración recomendada en producción.

Claves y sales: para qué sirven de verdad

El archivo de ejemplo wp-config-sample.php define ocho constantes: AUTH_KEY, SECURE_AUTH_KEY, LOGGED_IN_KEY, NONCE_KEY y sus cuatro sales asociadas. Sirven para firmar las cookies de sesión y los tokens de seguridad (nonces) de WordPress. Un atacante que las conozca puede fabricar cookies válidas; un sitio que conserva los valores de ejemplo está, por tanto, gravemente expuesto.

Hay que corregir dos ideas equivocadas:

  • no sirven para cifrar con hash las contraseñas de los usuarios. Desde WordPress 6.8, estas se procesan con bcrypt, sin relación con esas constantes;
  • cambiarlas cierra la sesión de todo el mundo: el comentario del archivo de ejemplo lo indica, todas las sesiones dejan de ser válidas.

Genéralas con el servicio oficial https://api.wordpress.org/secret-key/1.1/salt/, que devuelve ocho líneas listas para pegar.

¿Hay que cambiarlas con regularidad?

No, no sin motivo. La propia documentación de bastionado de WordPress remite a un análisis técnico titulado «por qué no deberías cambiar tus sales». Su argumento: muchos plugins usan estos valores para cifrar datos, por ejemplo los secretos de la autenticación en dos pasos o claves de API. Cambiarlos deja esos datos ilegibles. Cámbialos cuando hayan podido filtrarse: sitio hackeado, copia de seguridad expuesta, archivo publicado por error, antiguo proveedor.

Desactivar el editor de archivos: DISALLOW_FILE_EDIT

Por defecto, un administrador puede modificar el código PHP de los temas y plugins desde el Escritorio. Si alguien roba una cuenta de administrador, el editor se convierte en una vía directa para inyectar código.

define( 'DISALLOW_FILE_EDIT', true );

Según la guía de bastionado de WordPress, esta línea equivale a retirar las capacidades edit_themes, edit_plugins y edit_files. La misma guía señala sus límites: no impide que un atacante suba archivos maliciosos por otras vías. Es una medida sin efectos secundarios para casi todos los sitios, que conviene aplicar siempre.

DISALLOW_FILE_MODS: más estricto y más arriesgado

DISALLOW_FILE_MODS va más allá: también bloquea la instalación y la actualización de plugins y temas desde el Escritorio. Pero el código de WordPress revela un efecto menos conocido: la función wp_is_file_mod_allowed() devuelve falso en todos los contextos, incluido el del sistema de actualizaciones automáticas. Con esta constante, las actualizaciones menores de seguridad del núcleo ya no se instalan solas.

Resérvala para los sitios cuyas actualizaciones se despliegan por otra vía (Git, herramienta de despliegue, proveedor de alojamiento), con un proceso que realmente siga los parches.

FORCE_SSL_ADMIN: a menudo ya está activo

FORCE_SSL_ADMIN obliga a usar HTTPS en el acceso y en la administración, para que las contraseñas y las cookies nunca circulen en claro. El archivo default-constants.php muestra que, si no la defines, WordPress la pone automáticamente a verdadero cuando la dirección del sitio empieza por https. Definirla de forma explícita sigue siendo útil para documentar la decisión, o cuando la dirección guardada todavía está en http. La antigua constante FORCE_SSL_LOGIN está obsoleta desde WordPress 4.0.

WP_DEBUG en producción

La depuración es imprescindible en desarrollo y peligrosa en producción por dos motivos.

  • La visualización de errores (WP_DEBUG_DISPLAY, verdadero por defecto cuando WP_DEBUG está activo) revela rutas de archivos, consultas y nombres de plugins a cualquier visitante.
  • El registro (WP_DEBUG_LOG a true) se escribe por defecto en wp-content/debug.log, una dirección que conocen todos los bots. Puede contener datos sensibles: en 2024, una vulnerabilidad de LiteSpeed Cache (CVE-2024-44000) se basaba precisamente en cookies de sesión escritas en ese archivo.

En producción, mantén WP_DEBUG a false. Para un diagnóstico puntual, desde WordPress 5.1 WP_DEBUG_LOG acepta una ruta: coloca el registro fuera de la raíz web y desactiva la visualización.

define( 'WP_DEBUG', true );
define( 'WP_DEBUG_DISPLAY', false );
define( 'WP_DEBUG_LOG', '/home/cuenta/logs/wp-debug.log' ); // fuera de la raíz web

Elimina estas líneas y el archivo de registro una vez resuelto el problema.

Tres columnas de constantes: para añadir (DISALLOW_FILE_EDIT, WP_DEBUG a false, claves únicas), para comprobar (FORCE_SSL_ADMIN, actualizaciones automáticas, entorno), con precaución (DISALLOW_FILE_MODS, rotación de las sales, registro de depuración)
Las constantes de seguridad clasificadas por nivel de riesgo.
ConstanteValor recomendado en producciónEfecto comprobadoTrampa
Claves y salesValores únicos generadosFirman cookies y noncesCambiarlas cierra la sesión de todos y puede romper datos cifrados
DISALLOW_FILE_EDITtrueElimina el editor de archivosNinguna para la mayoría de los sitios
DISALLOW_FILE_MODSSolo con un despliegue externoBloquea instalaciones y actualizacionesTambién desactiva las actualizaciones automáticas
FORCE_SSL_ADMINtrueAdministración en HTTPSYa es verdadero por defecto si la dirección del sitio está en https
WP_DEBUGfalseDesactiva el modo de depuraciónRegistro público por defecto en wp-content
WP_AUTO_UPDATE_CORE'minor' (por defecto) o trueRegula las actualizaciones automáticas del núcleofalse desactiva también los parches de seguridad
WP_ENVIRONMENT_TYPE'production'Indica el tipo de entornoValor desconocido: production por defecto
Resumen de las constantes de seguridad

Dónde colocar wp-config.php

Un nivel por encima de la raíz

El archivo wp-load.php busca wp-config.php en la carpeta de WordPress y, si no lo encuentra, un nivel por encima, siempre que esa carpeta superior no contenga a su vez un wp-settings.php (para no confundir dos instalaciones anidadas). Colocar el archivo fuera de la raíz web garantiza que nunca se podrá servir con una simple petición.

Árbol de carpetas con wp-config.php colocado por encima de la carpeta public_html, y los tres pasos de búsqueda de wp-load.php
WordPress encuentra por sí solo un wp-config.php situado un nivel por encima de su raíz.

La guía de bastionado de WordPress reconoce que el beneficio es discutible: mientras PHP funcione, el archivo nunca se muestra, porque se ejecuta. Moverlo protege sobre todo en el caso de que el servidor dejara de ejecutar PHP y sirviera los archivos como texto plano. En un alojamiento compartido donde WordPress está instalado directamente en public_html, es sencillo y no entraña riesgo; en una subcarpeta, revisa la estructura.

Permisos y bloqueo en el servidor

  • Permisos: la guía de bastionado recomienda que solo tú y el servidor web podáis leer el archivo, lo que suele corresponder a 400 o 440. Según el proveedor, puede que hagan falta 600 o 640.
  • Con Apache o LiteSpeed, un bloque <Files "wp-config.php"> que contenga Require all denied en el .htaccess bloquea las peticiones directas.
  • No dejes nunca copias olvidadas: wp-config.php.bak, wp-config.old o wp-config.php~ no las ejecuta PHP y se servirían como texto plano, contraseñas incluidas.

Con WP Masquerade

WP Masquerade nunca modifica wp-config.php ni los archivos del núcleo. Las trampas para bots de la versión gratuita cuentan las peticiones a archivos sensibles como las copias .bak, lo que muestra qué buscan los bots en tu sitio. Con la versión Pro, la autenticación en dos pasos cifra los secretos de los usuarios con las claves del sitio: su guía recuerda que, tras cambiar las claves, hay que acceder con un código de recuperación y volver a activar la autenticación en dos pasos. El control de integridad compara los archivos del núcleo con las sumas oficiales y excluye a propósito wp-config.php, que es propio de cada sitio.

Vídeo en francés (WPMarmite): tres ideas equivocadas sobre el archivo wp-config.php y su seguridad.
Vídeo en francés: mover el archivo wp-config.php fuera de la raíz web.

Lee también: Entender los errores de WordPress y depurar tu web.

Lee también: Cómo instalar WordPress multisitio y crear una red de sitios.

Lo esencial

  • Las claves y sales firman cookies y nonces; genéralas con el servicio oficial y cámbialas solo si se han filtrado.
  • DISALLOW_FILE_EDIT es una medida segura; DISALLOW_FILE_MODS también desactiva las actualizaciones automáticas.
  • FORCE_SSL_ADMIN ya está activo por defecto si la dirección del sitio está en https.
  • En producción: WP_DEBUG a false, y nunca un registro en una carpeta pública.
  • WordPress admite colocar wp-config.php un nivel por encima; elimina cualquier copia de seguridad del archivo.

Fuentes

Otras fuentes consultadas: páginas oficiales de los editores y publicaciones de investigadores de seguridad.

Seguridad de WordPress, sin ruido

Un correo cuando importa: nuevos ataques observados, actualizaciones de la extensión y guías prácticas. Sin spam, baja con un clic.

Empieza gratis y pasa a Pro cuando estés listo

La versión gratuita ya oculta WordPress y cambia la dirección de la página de acceso. Pro añade alias, verificación en dos pasos y supervisión.