Objetivo del endurecimiento: reducir superficie y filtrar accesos
En Apache, “seguridad esencial” significa dos cosas: (1) exponer la menor información posible y (2) permitir únicamente lo necesario. Esto se traduce en directivas que reducen pistas para un atacante (versiones, firmas), recortan funcionalidades no usadas (métodos HTTP, listados), y aplican control de acceso moderno con Require para proteger rutas y recursos sensibles.
Endurecimiento básico desde el primer día (paso a paso)
1) Ocultar información innecesaria: ServerTokens y ServerSignature
Apache puede revelar detalles en la cabecera Server y en páginas de error. Minimizar esa información reduce el “fingerprinting”. Configura en el contexto global (por ejemplo en apache2.conf o un archivo incluido en conf-enabled/ o conf.d/):
ServerTokens Prod
ServerSignature OffServerTokens Prod: intenta limitar la cabeceraServera un valor genérico (sin versión/módulos).ServerSignature Off: evita que Apache firme páginas de error/autoindex con versión y host.
Validación rápida (cabeceras):
curl -I http://tu-dominio-o-ip/Revisa que la cabecera Server no exponga versión. Nota: algunos sistemas/proxies pueden añadir o modificar cabeceras; valida en el punto de exposición real.
2) Limitar métodos HTTP (GET/POST/HEAD) y bloquear el resto
Muchos sitios solo necesitan GET, POST y HEAD. Métodos como PUT, DELETE, TRACE o OPTIONS pueden ampliar la superficie si no se controlan. Puedes restringir por ubicación con <Location> o por directorio con <Directory>. Ejemplo conservador para todo el sitio:
- Escuche el audio con la pantalla apagada.
- Obtenga un certificado al finalizar.
- ¡Más de 5000 cursos para que explores!
Descargar la aplicación
<Location />
<LimitExcept GET POST HEAD>
Require all denied
</LimitExcept>
</Location>Si necesitas permitir OPTIONS para una API o CORS, hazlo solo en esa ruta específica, no globalmente.
Validación (probar métodos):
curl -i -X TRACE http://tu-dominio-o-ip/
curl -i -X PUT http://tu-dominio-o-ip/ -d 'test'
curl -i -X DELETE http://tu-dominio-o-ip/Lo esperado es 403 Forbidden (o 405 Method Not Allowed según tu configuración y aplicación), pero lo importante es que no se ejecute la acción.
3) Desactivar listados de directorios (Indexes)
El listado de directorios expone nombres de archivos, backups, scripts y estructura interna. Asegúrate de desactivar Indexes en el árbol publicado. Ejemplo recomendado:
<Directory /var/www/html>
Options -Indexes
</Directory>Si necesitas Indexes para un directorio de descargas, habilítalo solo ahí y con control de acceso, evitando que sea accidentalmente global.
Validación: visita una carpeta sin index.html y confirma que no aparece un listado, sino un error (403) o una respuesta controlada por tu aplicación.
4) Restringir FollowSymLinks según necesidad
FollowSymLinks permite que Apache siga enlaces simbólicos. Puede ser útil, pero también puede abrir rutas inesperadas si se crean symlinks hacia ubicaciones sensibles. En general:
- Si no necesitas symlinks: desactívalo.
- Si los necesitas: considera
SymLinksIfOwnerMatchpara reducir riesgo.
Ejemplo seguro por defecto:
<Directory /var/www/html>
Options -FollowSymLinks
</Directory>Ejemplo alternativo (si tu despliegue usa symlinks controlados):
<Directory /var/www/html>
Options +SymLinksIfOwnerMatch
</Directory>Validación: crea un symlink de prueba en el DocumentRoot apuntando a un directorio fuera del sitio y verifica si se puede acceder. Ajusta hasta que el comportamiento sea el esperado.
Control de acceso moderno con Require (autorización)
Concepto: autenticación vs autorización
Require controla quién está autorizado a acceder a un recurso. Puede usarse solo (por IP/red, por host, por expresiones) o combinado con autenticación (usuarios/grupos) cuando corresponda. En Apache moderno, Require reemplaza enfoques antiguos basados en Order/Deny/Allow.
Reglas por directorio (recomendado para contenido en disco)
Para controlar acceso a una carpeta del sistema de archivos, usa <Directory>. Ejemplo: permitir solo una red interna a /var/www/html/admin:
<Directory /var/www/html/admin>
Require ip 192.168.10.0/24
</Directory>Para denegar a todos por defecto y permitir solo a un rango:
<Directory /var/www/html/admin>
Require all denied
Require ip 192.168.10.0/24
</Directory>Cuando hay múltiples Require, Apache suele tratarlos como “OR” (si cualquiera cumple, pasa). Si necesitas lógica explícita, usa contenedores:
<Directory /var/www/html/admin>
<RequireAll>
Require ip 192.168.10.0/24
Require not ip 192.168.10.50
</RequireAll>
</Directory>Reglas por ubicación (URL) para rutas que no mapean 1:1 a disco
Para proteger endpoints por URL (por ejemplo, rutas generadas por una app o un proxy), usa <Location> o <LocationMatch>. Ejemplo: bloquear acceso a una ruta sensible expuesta por URL:
<Location /internal/>
Require all denied
</Location>Ejemplo con patrón (bloquear acceso a archivos ocultos tipo .git o .env si llegaran a estar bajo el árbol publicado):
<LocationMatch "(?i)/\.(git|svn|hg)(/|$)">
Require all denied
</LocationMatch>
<LocationMatch "(?i)/\.env$">
Require all denied
</LocationMatch>Nota práctica: para archivos en disco suele ser más robusto usar <Directory> o <FilesMatch>; para rutas puramente URL, <Location> es el enfoque.
Protección de rutas y archivos sensibles (recetas comunes)
Bloquear archivos de backup y temporales que a menudo se filtran por error:
<FilesMatch "(?i)\.(bak|old|orig|swp|tmp)$">
Require all denied
</FilesMatch>Bloquear acceso a archivos de configuración comunes si estuvieran dentro del DocumentRoot (idealmente no deberían estar ahí):
<FilesMatch "(?i)^(composer\.(json|lock)|package\.json|yarn\.lock|webpack\.config\.js)$">
Require all denied
</FilesMatch>Proteger un panel de administración por IP y además exigir autenticación (si aplica en tu entorno):
<Location /admin/>
<RequireAll>
Require ip 192.168.10.0/24
Require valid-user
</RequireAll>
</Location>En este último caso, recuerda que Require valid-user necesita que configures un proveedor de autenticación (por ejemplo Basic con un archivo de contraseñas) en ese mismo contexto o superior.
Validar cambios: inspección de cabeceras y escaneo básico de exposición
Checklist de verificación con curl
| Objetivo | Comando | Qué revisar |
|---|---|---|
| Ver cabeceras | curl -I http://host/ | Server sin versión; respuestas coherentes |
| Probar métodos | curl -i -X TRACE http://host/ | Bloqueo (403/405) |
| Probar listados | curl -i http://host/carpeta-sin-index/ | No debe listar archivos |
| Probar rutas sensibles | curl -i http://host/.git/ | Denegado |
Escaneo básico de exposición con herramientas comunes
Para una revisión rápida de superficie expuesta, puedes usar un escáner de cabeceras y endpoints. Ejemplos:
Enumeración de métodos permitidos (si el servidor responde a
OPTIONS):curl -i -X OPTIONS http://host/Si devuelve
Allow:con métodos no deseados, ajusta<LimitExcept>o reglas específicas por ruta.Escaneo ligero de configuración y cabeceras (según disponibilidad en tu entorno):
nmap --script http-methods,http-headers -p 80,443 host
Interpreta resultados con criterio: un hallazgo no siempre es explotable, pero sí indica superficie. La meta es que el servidor solo exponga lo que tu aplicación necesita.
Criterios de revisión: directivas críticas y errores comunes a evitar
Directivas críticas a revisar en cada despliegue
ServerTokensyServerSignature: deben minimizar información.Optionsen directorios publicados: evitarIndexes; evaluarFollowSymLinksy preferir el mínimo necesario.- Restricción de métodos con
<LimitExcept>: permitir solo lo requerido, con excepciones puntuales. - Reglas
Requireen rutas sensibles: paneles, endpoints internos, archivos ocultos, backups. - Alcance correcto de reglas: usar
<Directory>para rutas en disco y<Location>para URLs; evitar mezclar sin entender el impacto.
Configuraciones inseguras comunes (y cómo evitarlas)
Permitir listados por accidente: ocurre cuando en algún bloque queda
Options IndexesoOptions +Indexes. Mitigación: establece un baseline seguro en el directorio raíz del sitio conOptions -Indexesy habilita solo donde sea imprescindible.Exponer symlinks hacia rutas sensibles: si se permite
FollowSymLinkssin control, un symlink puede publicar contenido fuera del sitio. Mitigación: desactivar o usarSymLinksIfOwnerMatchy controlar permisos/propiedad.Reglas de acceso demasiado amplias: por ejemplo,
Require all granteden un bloque que termina aplicando a rutas administrativas. Mitigación: define primero “denegar por defecto” en rutas sensibles y permite explícitamente lo necesario.Confiar en bloqueos por URL cuando el recurso está en disco: a veces
<Location>no cubre variantes o alias. Mitigación: para archivos reales usa<Directory>/<FilesMatch>y valida con peticiones directas.Permitir métodos no usados: dejar
PUT/DELETEhabilitados puede abrir vectores si algún módulo o app los acepta. Mitigación: restringe globalmente y abre solo en endpoints concretos si es imprescindible.