El archivo .htaccess (Hypertext Access) es un fichero de configuración distribuida que Apache HTTP Server procesa a nivel de directorio. Aunque su propósito original no fue la seguridad, las directivas disponibles — especialmente a través de mod_rewrite y mod_authz — permiten implementar capas de protección efectivas contra ataques web comunes como inyección SQL, Cross-Site Scripting (XSS), CRLF injection y escaneo automatizado.
Qué es .htaccess y cuándo usarlo
El archivo .htaccess se coloca en cualquier directorio servido por Apache y sus directivas se aplican recursivamente a ese directorio y todos sus subdirectorios. Apache lo lee en cada petición HTTP, lo que implica un coste de rendimiento comparado con la configuración en httpd.conf o en bloques <VirtualHost>.
Utiliza .htaccess cuando:
- No tienes acceso a la configuración principal del servidor (hosting compartido).
- Necesitas reglas específicas por directorio que puedan modificarse sin reiniciar Apache.
- Quieres añadir una capa adicional de defensa en profundidad.
Si tienes acceso root al servidor, es preferible colocar las reglas directamente en la configuración del VirtualHost por rendimiento. Sin embargo, las reglas que veremos son igualmente válidas en ambos contextos.
Configuración base y ocultación de información
El primer paso es habilitar mod_rewrite y desactivar la exposición de información del servidor:
# Habilitar mod_rewrite
RewriteEngine On
Options +FollowSymLinks
# Ocultar la versión de Apache en páginas de error y cabeceras
ServerSignature Off
# Prevenir listado de directorios
Options -Indexes
# Proteger el propio archivo .htaccess
<Files .htaccess>
Order Allow,Deny
Deny from all
</Files>La directiva ServerSignature Off evita que Apache revele su versión y módulos instalados en las páginas de error (403, 404, 500). Esta información es valiosa para un atacante que busca vulnerabilidades conocidas en versiones específicas. Complementa esto con ServerTokens Prod en la configuración principal si tienes acceso.
Bloqueo de métodos HTTP no deseados
La mayoría de aplicaciones web solo necesitan los métodos GET y POST. Métodos como TRACE, DELETE o TRACK pueden ser explotados para ataques de Cross-Site Tracing (XST) o manipulación no autorizada de recursos:
# Bloquear métodos HTTP peligrosos
RewriteCond %{REQUEST_METHOD} ^(HEAD|TRACE|DELETE|TRACK|OPTIONS) [NC]
RewriteRule ^(.*)$ - [F,L]Los flags utilizados en las reglas son:
[NC]— No Case: la comparación no distingue mayúsculas de minúsculas.[OR]— Encadena la condición con la siguiente usando OR lógico (por defecto es AND).[F]— Forbidden: devuelve un error 403.[L]— Last: detiene el procesamiento de reglas posteriores.
Protección contra CRLF Injection
La inyección CRLF (Carriage Return Line Feed) ocurre cuando un atacante inserta caracteres de nueva línea (%0A, %0D) en las cabeceras HTTP. Esto puede derivar en HTTP Response Splitting, envenenamiento de caché o XSS:
# Bloquear CRLF en la petición completa
RewriteCond %{THE_REQUEST} ^.*(\\r|\\n|%0A|%0D).* [NC]
RewriteRule ^(.*)$ - [F,L]Sanitización de cabeceras HTTP
Las cabeceras Referer y Cookie son vectores frecuentes de inyección. Un atacante puede insertar caracteres especiales en estas cabeceras para intentar XSS reflejado o manipulación de la aplicación:
# Bloquear caracteres peligrosos en Referer
RewriteCond %{HTTP_REFERER} ^(.*)(<|>|'|%0A|%0D|%27|%3C|%3E|%00).* [NC,OR]
# Bloquear caracteres peligrosos en Cookie
RewriteCond %{HTTP_COOKIE} ^.*(<|>|'|%0A|%0D|%27|%3C|%3E|%00).* [NC]
RewriteRule ^(.*)$ - [F,L]Los caracteres bloqueados incluyen: comillas simples (%27), etiquetas HTML (%3C, %3E), bytes nulos (%00) y saltos de línea (%0A, %0D). Ninguno de estos debería aparecer en peticiones legítimas.
Protección contra overflow en la URI
Las peticiones con URIs extremadamente largas pueden indicar intentos de buffer overflow, especialmente en servidores con componentes vulnerables como versiones antiguas de Apache Tomcat:
# Bloquear URIs con caracteres sospechosos y longitudes excesivas
RewriteCond %{REQUEST_URI} ^/(,|;|:|<|>|">|"<|/|\\\.\.\\).{0,9999}.* [NC]
RewriteRule ^(.*)$ - [F,L]Bloqueo de User-Agents maliciosos
Los bots maliciosos, escáneres de vulnerabilidades y herramientas automatizadas suelen identificarse con User-Agents característicos. Bloquearlos reduce significativamente el ruido de ataques automatizados:
# Bloquear peticiones sin User-Agent
RewriteCond %{HTTP_USER_AGENT} ^$ [OR]
# Bloquear herramientas de línea de comandos
RewriteCond %{HTTP_USER_AGENT} ^(java|curl|wget).* [NC,OR]
# Bloquear scrapers y harvesting tools
RewriteCond %{HTTP_USER_AGENT} ^.*(winhttp|HTTrack|clshttp|archiver|loader|email|harvest|extract|grab|miner).* [NC,OR]
# Bloquear escáneres de vulnerabilidades conocidos
RewriteCond %{HTTP_USER_AGENT} ^.*(libwww|curl|wget|python|nikto|scan|sqlmap|nmap|masscan|dirbuster|gobuster).* [NC,OR]
# Bloquear User-Agents con caracteres de inyección
RewriteCond %{HTTP_USER_AGENT} ^.*(<|>|'|%0A|%0D|%27|%3C|%3E|%00).* [NC]
RewriteRule ^(.*)$ - [F,L]Nota: Bloquear por User-Agent es una medida superficial ya que cualquier atacante competente puede falsificarlo. Sin embargo, es efectiva contra bots automatizados que no se molestan en cambiar su identificación.
Protección contra SQL Injection y XSS
El QUERY_STRING (los parámetros después del ? en la URL) es el vector principal para inyecciones SQL y XSS. Estas reglas bloquean patrones comunes de ataque:
# Bloquear palabras clave SQL combinadas con caracteres de inyección
RewriteCond %{QUERY_STRING} ^.*(;|<|>|'|"|\)|%0A|%0D|%22|%27|%3C|%3E|%00).*(/\*|union|select|insert|cast|set|declare|drop|update|md5|benchmark).* [NC,OR]
# Bloquear referencias a localhost (posible SSRF)
RewriteCond %{QUERY_STRING} ^.*(localhost|loopback|127\.0\.0\.1).* [NC,OR]
# Bloquear caracteres de inyección en query string
RewriteCond %{QUERY_STRING} ^.*(<|>|'|%0A|%0D|%27|%3C|%3E|%00).* [NC]
RewriteRule ^(.*)$ - [F,L]Estas reglas detectan patrones como ?id=1' UNION SELECT, ?q=<script> o intentos de acceder a localhost a través de parámetros (Server-Side Request Forgery). La combinación de caracteres especiales con palabras clave SQL reduce los falsos positivos.
Regla completa consolidada
Aquí está el archivo .htaccess completo con todas las reglas combinadas y la acción de respuesta:
RewriteEngine On
Options +FollowSymLinks -Indexes
ServerSignature Off
# Proteger .htaccess
<Files .htaccess>
Order Allow,Deny
Deny from all
</Files>
# --- Métodos HTTP ---
RewriteCond %{REQUEST_METHOD} ^(HEAD|TRACE|DELETE|TRACK) [NC,OR]
# --- CRLF Injection ---
RewriteCond %{THE_REQUEST} ^.*(\\r|\\n|%0A|%0D).* [NC,OR]
# --- Cabeceras ---
RewriteCond %{HTTP_REFERER} ^(.*)(<|>|'|%0A|%0D|%27|%3C|%3E|%00).* [NC,OR]
RewriteCond %{HTTP_COOKIE} ^.*(<|>|'|%0A|%0D|%27|%3C|%3E|%00).* [NC,OR]
# --- URI Overflow ---
RewriteCond %{REQUEST_URI} ^/(,|;|:|<|>|">|"<|/|\\\.\.\\).{0,9999}.* [NC,OR]
# --- User-Agents ---
RewriteCond %{HTTP_USER_AGENT} ^$ [OR]
RewriteCond %{HTTP_USER_AGENT} ^(java|curl|wget).* [NC,OR]
RewriteCond %{HTTP_USER_AGENT} ^.*(winhttp|HTTrack|clshttp|archiver|loader|email|harvest|extract|grab|miner).* [NC,OR]
RewriteCond %{HTTP_USER_AGENT} ^.*(libwww|python|nikto|scan|sqlmap|nmap|masscan|dirbuster|gobuster).* [NC,OR]
RewriteCond %{HTTP_USER_AGENT} ^.*(<|>|'|%0A|%0D|%27|%3C|%3E|%00).* [NC,OR]
# --- SQL Injection / XSS ---
RewriteCond %{QUERY_STRING} ^.*(;|<|>|'|"|\)|%0A|%0D|%22|%27|%3C|%3E|%00).*(/\*|union|select|insert|cast|set|declare|drop|update|md5|benchmark).* [NC,OR]
RewriteCond %{QUERY_STRING} ^.*(localhost|loopback|127\.0\.0\.1).* [NC,OR]
RewriteCond %{QUERY_STRING} ^.*(<|>|'|%0A|%0D|%27|%3C|%3E|%00).* [NC]
# Acción: devolver 403 Forbidden
RewriteRule ^(.*)$ - [F,L]La acción [F,L] devuelve un error 403 Forbidden al cliente. Alternativamente, puedes redirigir a un script de logging para registrar los intentos de ataque:
# Alternativa: redirigir a un script que registre el intento
RewriteRule ^(.*)$ /security_log.php [L]Cabeceras de seguridad adicionales
Complementa las reglas de rewrite con cabeceras HTTP de seguridad usando mod_headers:
<IfModule mod_headers.c>
# Prevenir clickjacking
Header always set X-Frame-Options "SAMEORIGIN"
# Activar protección XSS del navegador
Header always set X-XSS-Protection "1; mode=block"
# Prevenir MIME sniffing
Header always set X-Content-Type-Options "nosniff"
# Política de referrer
Header always set Referrer-Policy "strict-origin-when-cross-origin"
# Forzar HTTPS
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
# Content Security Policy básica
Header always set Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'"
</IfModule>Limitaciones y consideraciones
Es importante entender que las reglas .htaccess son una capa de defensa complementaria, no un sustituto de la seguridad a nivel de aplicación:
- Falsos positivos — Reglas demasiado agresivas pueden bloquear usuarios legítimos. Monitoriza los logs de error de Apache tras implementar las reglas.
- Evasión — Un atacante experimentado puede codificar sus payloads de formas que eviten las expresiones regulares (doble codificación URL, Unicode, etc.).
- User-Agent spoofing — Falsificar el User-Agent es trivial, así que no confíes en él como única defensa.
- Rendimiento — Apache procesa
.htaccessen cada petición. En sitios de alto tráfico, mueve las reglas a la configuración del VirtualHost. - WAF dedicado — Para una protección más robusta, considera usar ModSecurity con el OWASP Core Rule Set (CRS), que ofrece detección más sofisticada y mantenida por la comunidad.
Las reglas presentadas aquí siguen siendo útiles como primera línea de defensa rápida en entornos donde no se dispone de un WAF completo. La clave está en combinarlas con buenas prácticas de desarrollo seguro: validación de entrada en el servidor, consultas parametrizadas, escape de salida y el principio de mínimo privilegio.
:wq!
Comentarios