La “llave maestra” de tu aplicación: principios para proteger configuraciones sensibles (con foco en wp-config.php)
Toda aplicación tiene una llave maestra: el archivo (o archivos) donde viven credenciales de base de datos, claves de cifrado, salts, tokens de APIs y ajustes críticos. Si caen en manos equivocadas, pueden comprometer todo: datos, identidad, reputación y negocio. Aquí verás los principios universales para proteger configuraciones sensibles, y al final, bajaremos a tierra con WordPress y su wp-config.php.
1) Por qué importa: qué hay en un archivo de configuración
Los archivos de configuración contienen secretos y parámetros críticos. Algunos ejemplos:
- Credenciales de base de datos (
DB_USER,DB_PASSWORD, host, nombre). - Claves de API (pagos, email transaccional, mapas, IA, analítica).
- Salts y keys criptográficas (autenticación, cookies, JWT, cifrados).
- Parámetros de seguridad (dominios permitidos, orígenes CORS, modos debug, rutas internas).
- Flags de entorno (producción vs desarrollo), feature flags, endpoints privados.
Una filtración de estos datos permite conexiones a tu BD, suplantación de usuarios, envío de correos “legítimos” desde tus cuentas o exfiltración de información. Por eso tratamos la configuración como activo de alto valor.
2) Amenazas reales: qué puede salir mal (y cómo sucede)
- Exposición directa por servidor: el archivo es servible (mala configuración) o queda en un directorio público y se descarga.
- Errores de control de versiones: subir secretos a un repo (Git). Aunque borres el commit, el histórico o forks pueden conservarlo.
- Modos debug activos: vuelcan variables de entorno, rutas, claves o trazas con información sensible.
- Permisos laxos: el proceso equivocado (o un usuario no autorizado) puede leer el archivo.
- Backups mal protegidos: copias en buckets públicos, enlaces temporales sin caducidad real, snapshots sin cifrar.
- Logs verbosos: volcados de errores que incluyen rutas, queries, tokens o fragmentos del archivo.
- Fugas por terceros: integraciones, proveedores o plugins que copian configuraciones para soporte.
Conclusión: no basta con “ocultar un archivo”. Necesitas defensa en profundidad (múltiples capas) y hábitos consistentes.
3) Principios universales de protección
- Mínimo privilegio: cada proceso ve sólo lo que necesita, y nada más.
- Segregación: separa secretos del código y del contenido público.
- Rotación: caducidad y renovación periódica de claves.
- Observabilidad: detecta accesos inusuales o fallos de permisos.
- Automatización: scripts y pipelines que imponen reglas (CI/CD con escáneres de secretos).
- Revisión de pares: cambios en configuración crítica requieren doble validación.
- Backups seguros: cifrados, con control de acceso, y restauración probada.
4) Permisos y propiedad: el mínimo indispensable
En servidores Linux/Unix, los permisos y el usuario que “posee” el archivo son decisivos.
- Propietario: el usuario del proceso web/PHP-FPM (p. ej.,
www-dataonginx) debe poder leer, no escribir. - Grupo: ajusta según tu política (a menudo, sin lectura para el resto).
- Otros: sin acceso (
---).
# Ejemplo de permisos estrictos
chown root:www-data /ruta/segura/wp-config.php
chmod 640 /ruta/segura/wp-config.php
Si subes aún más la seguridad:
- Propietario root (sólo root escribe), grupo del proceso web solo lectura.
- SELinux/AppArmor: perfila qué binarios pueden leer qué rutas.
Regla de oro: si el proceso web no necesita escribir, no permitas escritura.
5) Rutas y exposición: dónde vive tu configuración
La ubicación reduce el riesgo:
- Fuera del docroot: almacena la configuración fuera de la carpeta pública (
public/,html/,www/). Así, aunque el servidor sirva estáticos, no podrá entregar el archivo. - Bloqueo explícito en el servidor: niega acceso por patrón de nombre (p. ej.,
wp-config.php,.env), incluso si alguien lo coloca en un directorio público por error.
# Apache (.htaccess o conf del vhost)
<FilesMatch "^(wp-config\.php|\.env|composer\.(json|lock))$">
Require all denied
</FilesMatch>
# Nginx (vhost)
location ~* /(wp-config\.php|\.env|composer\.(json|lock))$ {
deny all;
return 404;
}
Evita rutas predecibles (como /backups/ públicos) y limpia archivos de ejemplo o readme expuestos.
6) Segregación de secretos y 12-Factor: variables de entorno, .env y gestores de secretos
Las buenas prácticas modernas (p. ej., The Twelve-Factor App: Config) recomiendan sacar la configuración fuera del código. Opciones:
- Variables de entorno (
ENV VARS): inyectadas por sistema, contenedor o plataforma. - Archivo
.env: leído por tu app (no lo subas nunca al repo). - Secret managers: AWS Secrets Manager, GCP Secret Manager, HashiCorp Vault, Doppler… Control de acceso, rotación y auditoría centralizados.
Ventajas de los gestores: rotación automática, versionado, permisos finos, auditoría. Desventajas: complejidad y coste si tu proyecto es pequeño. Elige en función de tu escala.
7) Rotación, caducidad y secret hygiene
Sin rotación, cada filtración accidental se vuelve permanente. Políticas mínimas:
- Caducidad de credenciales (trimestral/semestral según criticidad).
- Rotación inmediata ante sospecha de exposición.
- Separación por entorno (dev, staging, prod) con credenciales distintas.
- Principio de blast radius: que una exposición afecte lo mínimo (bases separadas, accesos limitados por rol/IP).
Automatiza recordatorios de rotación y valida que la app levanta correctamente después (pipelines de CI con pruebas de “smoke”).
8) Registro, auditoría y alertas: observa lo que importa
La seguridad sin observabilidad es humo. Necesitas:
- Logs de acceso (quién leyó qué, cuándo).
- Alertas por lectura/escritura anómala de archivos sensibles.
- Detección de secretos en repos (pre-commit gitleaks, trufflehog, GitHub secret scanning).
- Monitoreo de integridad (AIDE, inotify, FIM) para detectar cambios inesperados.
Si usas gestores de secretos, habilita su auditoría nativa y notificaciones.
9) Cifrado en reposo y en tránsito: cuándo y cómo
En tránsito: TLS/HTTPS obligatorio para panel y APIs. En reposo: cifra discos/volúmenes y, si guardas copias de configuraciones, cifra los backups. Para datos especialmente sensibles, cifra valores de configuración con claves guardadas en HSM o secret manager.
Recuerda que el cifrado no arregla permisos excesivos: un proceso con permisos podrá leer claves descifradas. El cifrado complementa, no sustituye, el mínimo privilegio.
10) Infraestructura y capas: WAF, copias, backups y entorno
- WAF / CDN: bloquea patrones de descarga y escaneo de rutas conocidas (
.env,wp-config.php). - Backups: cifrados y en ubicación privada; evita URLs “secretas” sin autenticación.
- Entornos aislados: staging accesible con auth/IP; evita exponer staging con dominios “indexables”.
- Infra como código: declara reglas de acceso en Terraform/Ansible; revisa PRs antes de desplegar.
11) WordPress en la práctica: blindando wp-config.php
En WordPress, wp-config.php contiene credenciales de BD, prefijo de tablas, salts/keys y constantes de comportamiento. Protegerlo es prioridad alta. Pasos concretos:
11.1 Mover wp-config.php fuera del docroot
WordPress permite ubicarlo un nivel por encima del directorio público. Si tu docroot es /var/www/html, colócalo en /var/www/wp-config.php y WordPress lo leerá.
# Estructura
/var/www/wp-config.php
/var/www/html/index.php
/var/www/html/wp-includes/...
11.2 Permisos y propiedad restrictivos
chown root:www-data /var/www/wp-config.php
chmod 640 /var/www/wp-config.php
Si tu PHP-FPM corre como www-data, el grupo tiene lectura; el resto, no. Root (u otro usuario privilegiado) es el único que escribe.
11.3 Denegar acceso por servidor
# Apache (.htaccess en docroot o vhost)
<Files wp-config.php>
Require all denied
</Files>
# Nginx (vhost)
location = /wp-config.php { deny all; return 404; }
11.4 Salts y claves de autenticación
Genera claves fuertes y cámbialas si sospechas de exposición. Puedes obtenerlas desde el servicio oficial de WordPress (ábrelo en nueva pestaña): api.wordpress.org/secret-key/1.1/salt/
11.5 Desactivar WP_DEBUG en producción
define('WP_DEBUG', false);
define('WP_DEBUG_LOG', false);
define('WP_DEBUG_DISPLAY', false);
Evitas fugas en pantalla o logs indiscriminados. Si necesitas logs en prod, dirígelos a un archivo protegido y sanitizea mensajes.
11.6 Uso de variables de entorno
Puedes cargar valores desde el entorno y no escribirlos en claro:
// wp-config.php (ejemplo)
define('DB_NAME', getenv('WP_DB_NAME'));
define('DB_USER', getenv('WP_DB_USER'));
define('DB_PASSWORD', getenv('WP_DB_PASS'));
define('DB_HOST', getenv('WP_DB_HOST'));
Rellena esas variables en tu sistema (systemd, contenedor, plataforma) o a través de un gestor de secretos.
11.7 Prefijo de tablas y superficie de ataque
$table_prefix = 'wp_'; // cámbialo en instalaciones nuevas
No es una medida “antihacker” por sí misma, pero reduce ruido de ataques automatizados que asumen wp_. Si cambias en un sitio existente, migra con cuidado.
11.8 Forzar HTTPS y endurecer cabeceras
Protege cookies y transporte:
define('FORCE_SSL_ADMIN', true); // Admin siempre por HTTPS
Y configura cabeceras en el servidor (HSTS, X-Content-Type-Options, X-Frame-Options, CSP) acorde a tu app. Referencia general: MDN: HTTP Headers
11.9 Limitar edición de archivos desde el panel
define('DISALLOW_FILE_EDIT', true);
define('DISALLOW_FILE_MODS', true); // si gestionas updates por CI/CD
Quita a la interfaz la capacidad de editar plugins/temas en prod.
11.10 Copias y staging
- Backups cifrados, no servibles públicamente.
- Staging con auth básica/IP; evita indexación y reutilizar credenciales de prod.
- Inyecta secretos distintos por entorno; nunca los compartas.
12) Checklist final: 20 pasos para pasar a la acción hoy
- Mueve
wp-config.php(o tu config) fuera del docroot. - Aplica permisos mínimos (
640) y propiedad segura. - Deniega acceso por servidor a archivos de config y
.env. - Genera y actualiza salts/keys seguras.
- Desactiva debug en producción; dirige logs a ubicación segura.
- Extrae secretos a variables de entorno o secret manager.
- Usa credenciales distintas por entorno (dev/staging/prod).
- Configura rotación periódica y alertas de expiración.
- Implementa escáner de secretos en CI (pre-commit y en repos).
- Protege backups (cifrado, acceso privado, caducidad).
- Audita quién lee la configuración y cuándo.
- Endurece cabeceras y fuerza HTTPS en admin.
- Deshabilita edición de archivos desde el panel.
- Documenta ubicación de config y procedimiento de restauración.
- Verifica que staging no expone secretos ni usa credenciales de prod.
- Limita la superficie de plugins y elimina los que no uses.
- Prueba recuperación ante desastre (restauración de backup).
- Automatiza revisiones trimestrales de permisos y rutas.
- Revisa que ningún endpoint devuelva variables sensibles.
- Capacita al equipo (errores comunes: subir .env a Git, dejar debug on).
13) Recursos recomendados
- The Twelve-Factor App — Config: 12factor.net/config
- MDN — Cabeceras HTTP de seguridad: developer.mozilla.org/.../Headers
- WordPress — Salts/keys generator: api.wordpress.org/secret-key/1.1/salt/
- WordPress Developer — Seguridad y nonces: developer.wordpress.org/plugins/security/
- GitHub — Secret scanning (overview): docs.github.com/.../secret-scanning
- AWS Secrets Manager (conceptos): docs.aws.amazon.com/.../secretsmanager
14) FAQ
¿Mover wp-config.php fuera del docroot siempre funciona?
En instalaciones estándar, sí. En hostings gestionados puede variar. Comprueba rutas y permisos; WordPress intenta localizarlo automáticamente un nivel arriba.
¿Uso variables de entorno o .env?
Si puedes, variables de entorno (inyectadas por el sistema o el orquestador). Si usas .env, no lo subas al repo; niega acceso por servidor y asegúrate de que los backups estén cifrados.
¿Cambiar el prefijo de tablas wp_ me protege de todo?
No. Reduce ruido de bots automatizados, pero no sustituye permisos, rotación ni buenas prácticas.
¿Cómo gestiono claves de APIs de terceros en equipo?
Usa un secret manager con roles y auditoría. Evita compartirlas por chat. Documenta quién las rota y cuándo.
Dejé un repo público con secretos, ¿y ahora?
Revoca y rota inmediatamente. Busca instalaciones con esos secretos, revisa accesos y activa alertas. No confíes en “borré el commit”, porque puede persistir en clones y cachés.
Comentarios (0)
Aún no hay comentarios. ¡Sé el primero!
Deja tu comentario