Consejos de seguridad básicos para Apache.
Recopilación de diversas funciones útiles de seguridad por Jordi Ivars. 2007.
Lo más básico.
Oculta la versión y otra información delicada
Por defecto muchas instalaciones de Apache muestran el número de versión que está funcionando, el sistema operativo y un informe de módulos de Apache están instalados en el servidor. Los usuario maliciosos pueden utilizar esta información para atacar tu servidor.
Hay dos directivas que necesitas agregar, o corregir en tu archivo de httpd.conf:
ServerSignature Off
ServerTokens Prod
El ServerSignature aparece en la parte inferior de las páginas generadas por apache tales como los famosos errores 404.
La directiva ServerTokens se utiliza para determinarse lo que pondrá Apache en la cabecera de la respuesta HTTP del servidor.
Apache debe funcionar bajo su propia cuenta y grupo de usuario
Algunas versiones de Apache corren bajo el usuario nobody, esto compromete mucho su seguridad por lo tanto haz lo siguiente:
User apache
Group apache
Utiliza el mod_security
He dado con un excelente artículo que nos explica someramente cómo detener en seco el spam procedente de inyección en formularios Web a través de mod_security, un módulo especialmente creado para Apache.
La idea es bien sencilla: mod_security es un frontal de seguridad que se coloca delante del servidor Web, de modo que sus prestaciones puedan ser empleadas a efectos de aseguramiento del servidor.
ModSecurity es, a fin de cuentas, un sistema de detección de intrusos en forma de módulo de servidor, y está orientado a las aplicaciones Web. Es una especie de firewall, que inspecciona el tráfico tomando acciones contra el tráfico sospechoso, incluído el spam y los intentos de desbordamiento de búfer. Cuenta con un motor de registro que genera logs de todos los incidentes, que sin duda ayudará a resolver las situaciones dudosas.
Así pues, la primera acción que podemos ejecutar con este módulo es emplearlo de paraguas antispam, para frenar la inyección PHP, spam que por cierto sufren a diario gran cantidad de blogs y que últimamente se ha recrudecido severamente.
Este tipo de spam es el que insertan bots en todo tipo de infraestructuras de script, especialmente PHP,y cuya forma más común es incrustar comentarios y trackbacks publicitarios en blogs.
En el punto final de este documento podemos encontrar ampliado la utilización de mod_security.
Deshabilitar cualquier módulo innecesario
Apache viene por defecto instalado con un serie de módulos.Debes echarle un vistazo a la documentación de Apache y ver para que sirve cada uno de ellos, y de esta manera te darás cuenta de que hay algunos que no son útiles en tu servidor.
Aquí están algunos módulos que se instalan por defecto pero a menudo no son necesarios: mod_imap, mod_include, mod_info, mod_userdir, mod_status, mod_cgi, mod_autoindex.
Asegurarte de que los archivos a los que se accede son los deseados
No deseamos que se pueda acceder a los directorios que no tengan permisos para ello, supongamos que el directorio raiz para nuestras webs es /web, la configuración óptima debera ser la siguiente:
Desactiva las opciones para explorar directorios
Esto lo puedes hacer con las opciones de directiva dentro de la etiqueta directorio tiene dos posibles valores none o indexes.
Options -Indexes
Desactiva los includes del lado servidor
Esto también se hace con las opciones de directiva dentro de la etiqueta directorio tiene dos posibles valores none o include.
Options -Includes
Desactiva la ejecución de CGI
Si no necesitas la ejecución de CGI por algún motivo en concreto desacrivalos se hace con las opciones de directiva dentro de la etiqueta directorio tiene dos posibles valores none o ExecCGI.
Options -ExecCGI
No permitir que apache siga enlaces simbólicos
De nuevo se configura con las opciones de directiva dentro de la etiqueta directorio tiene dos posibles valores none o FollowSymLinks.
Options -FollowSymLinks
Desactivar todas las opciones
Si deseas desactivar el uso de todas las opciones simplemente:
Options None
Si solamente deseas desactivar algunas en concreto, separalas con un espacio en las opciones de directiva:
Options -ExecCGI -FollowSymLinks -Indexes
Desactivar la ayuda para los archivos .htaccess
Esto esta ya hecho pero con la directiva AllowOverride. Cámbialo a none.
AllowOverride None
Otra opción interesante sería bloquear la descarga de todos los archivos que comienzen con .ht por ejemplo, se haría de la siguiente manera:
AccessFileName .httpdoverride
Disminuye el valor máximo de tiempo de espera
Por el defecto el tiempo de espera es de 300 segundos. Puedes disminuirlo por seguridad para prevenir ataques de esta manera:
Timeout 45
Limitar el tamaño maximo de peticiones
Apache tiene varias directivas que permiten que limites el tamaño de una petición, esto puede ser muy útil.
Una buena manera de comenzar es con la directiva LimitRequestBody. Esta directiva esta fijada a ilimitado por defecto. Si estás permitiendo uploads de archivos que no sean mayores a 1MB, podrías fijar este ajuste a algo parecido a esto:
LimitRequestBody 1048576
Si no estás permitiendo uploads de archivos puedes fijarlo incluso a un tamaño más pequeño.
Algunos otras directivas a mirar son LimitRequestFields, LimitRequestFieldSize y LimitRequestLine.
Restricciones de acceso
Archivos .htaccess
Podemos hacer uso de archivos .htaccess para proteger ciertas zonas de nuestra web de usuarios no permitidos.
Solamente tenemos que crear un fichero .htaccess en el directorio que deseamos proteger, definiendo la autenticación para dicho directorio contra un fichero que incluye claves de acceso.
Como requisitos previos necesitamos tener cargados en nuestro apache los módulos mod_auth y mod_access.
Las directivas tratadas en éste artículo necesitarán ir en el archivo de configuración principal de su servidor (típicamente en una sección del tipo <Directory>), o en archivos de configuración por directorios (archivos .htaccess).
Si planea usar archivos .htaccess, necesitará tener una configuración en el servidor que permita poner directivas de autentificación en estos archivos. Esto se logra con la directiva AllowOverride, la cual especifica cuáles directivas, en caso de existir, pueden ser colocadas en los archivos de configuración por directorios.
Ya que se está hablando de autentificación, necesitará una directiva AllowOverride como la siguiente:
AllowOverride AuthConfig
O, si sólo va a colocar directivas directamente en el principal archivo de configuración del servidor, por supuesto necesitará tener permiso de escritura a ese archivo.
Y necesitará saber un poco acerca de la estructura de directorios de su servidor, con la finalidad de que sepa dónde están algunos archivos. Esto no debería ser muy difícil, y trataré de hacerlo sencillo cuando lleguemos a ese punto.
Y aquí está lo esencial en cuanto a proteger con contraseña un directorio de su servidor.
Necesitará crear un archivo de contraseñas. Éste archivo debería colocarlo en algún sitio no accesible mediante la Web. Por ejemplo, si sus documentos son servidos desde /usr/local/apache/htdocs usted podría querer colocar el(los) archivo(s) de contraseñas en /usr/local/apache/passwd.
Para crear un archivo de contraseñas, use la utilidad htpasswd que viene con Apache. Ésta utilidad puede encontrarla en el directorio bin de cualquier sitio en que haya instalado Apache. Para crear el archivo, escriba:
htpasswd -c /usr/local/apache/passwd/passwords rbowen
htpasswd le pedirá la contraseña, y luego se la volverá a pedir para confirmarla:
# htpasswd -c /usr/local/apache/passwd/passwords rbowen
New password: mypassword
Re-type new password: mypassword
Adding password for user rbowen
El siguiente paso es configurar el servidor para que solicite una contraseña y decirle al servidor a qué usuarios se les permite el acceso. Puede hacer esto editando el archivo httpd.conf o usando un archivo .htaccess. Por ejemplo, si desea proteger el directorio /usr/local/apache/htdocs/secret, puede usar las siguientes directivas, ya sea colocándolas en el archivo /usr/local/apache/htdocs/secret/.htaccess, o en httpd.conf dentro de una sección <Directory /usr/local/apache/apache/htdocs/secret>.
AuthType Basic
AuthName "Restricted Files"
AuthUserFile /usr/local/apache/passwd/passwords
Require user rbowen
Vamos a examinar cada una de estas directivas por separado. La directiva AuthType selecciona el método que se va a usar para autentificar al usuario. El método más común es Basic, y éste método está implementado en mod_auth. Es importante ser consciente, sin embargo, de que la autentificación Básica envía la contraseña desde el cliente hasta el navegador sin encriptar. Por lo tanto, este método no debería ser usado para información altamente sensible. Apache soporta otro método de autentificación: AuthType Digest. Este método está implementado en mod_auth_digest y es mucho más seguro. Sólo las versiones más recientes de clientes soportan la autentificación del tipo Digest.
La directiva AuthName establece el Dominio (Realm) a usar en la autentificación. El dominio (realm) cumple dos funciones importantes. Primero, el cliente frecuentemente presenta esta información al usuario como parte del cuatro de diálogo para la contraseña. Segundo, es usado por el cliente para determinar qué contraseña enviar para un área autentificada dada.
Así, por ejemplo, una vez que el cliente se haya autentificado en el área "Restricted Files", automáticamente se volverá a tratar de usar la misma contraseña en cualquier área del mismo servidor que esté marcado con el Dominio (Realm) "Restricted Files". Por lo tanto, puede evitar que se le pida al usuario la contraseña más de una vez permitiendo compartir el mismo dominio (realm) para múltiples áreas restringidas. Por supuesto, por razones de seguridad, el cliente siempre necesitará pedir de nuevo la contraseña cuando cambie el nombre de la máquina del servidor.
La directiva AuthUserFile establece la ruta al archivo de contraseña que acabamos de crear con htpasswd. Si tiene un gran número de usuarios, sería bastante lento buscar por medio de un archivo en texto plano para autentificar al usuario en cada solicitud. Apache también tiene la capacidad de almacenar la información del usuario en archivos rápidos de bases de datos. El módulo mod_auth_dbm proporciona la directiva AuthDBMUserFile. Estos archivos pueden ser creados y manipulados con el programa dbmmanage.
Finalmente, la directiva Require proporciona la parte de la autorización del proceso estableciendo el usuario al que se le permite acceder a ese área del servidor. En la próxima sección, discutimos varias formas de usar la directiva Require.
Las directivas anteriores sólo permiten que una persona (específicamente alguien con un nombre de usuario de rbowen) acceda al directorio. En la mayoría de los casos, usted querrá permitir el acceso a más de una persona. Aquí es donde entra la directiva AuthGroupFile.
Si desea permitir la entrada a más de una persona, necesitará crear un archivo de grupo que asocie nombres de grupo con una lista de usuarios perteneciente a ese grupo. El formato de este archivo es muy sencillo, y puede crearlo con su editor favorito. El contenido del archivo será parecido a este:
GroupName: rbowen dpitts sungo rshersey
Esto es solo una lista de miembros del grupo escritos en una línea separados por espacios.
Para agregar un usuario a un archivo de contraseñas ya existente, escriba:
htpasswd /usr/local/apache/passwd/passwords dpitts
Obtendrá la misma respuesta que antes, pero el nuevo usuario será agregado al archivo existente, en lugar de crear un nuevo archivo. (Es la opción -c la que se cree un nuevo archivo de contraseñas).
Ahora, necesita modificar su archivo .htaccess para que sea como el siguiente:
AuthType Basic
AuthName "By Invitation Only"
AuthUserFile /usr/local/apache/passwd/passwords
AuthGroupFile /usr/local/apache/passwd/groups
Require group GroupName
Ahora, cualquiera que esté listado en el grupo GroupName, y figure en el archivo password, se le permitirá el acceso, si escribe la contraseña correcta.
Existe otra manera de permitir entrar a múltiples usuarios que es menos específica. En lugar de crear un archivo de grupo, puede usar sólo la siguiente directiva:
Require valid-user
Usando eso en vez de la línea Require user rbowen, le permitirá el acceso a cualquiera que esté listado en el archivo de contraseñas y que haya introducido correctamente su contraseña. Incluso puede emular el comportamiento del grupo aquí, sólo manteniendo un archivo de contraseña para cada grupo. La ventaja de esta técnica es que Apache sólo tiene que verificar un archivo, en vez de dos. La desventaja es que usted tiene que mantener un grupo de archivos de contraseña, y recordar referirse al correcto en la directiva AuthUserFile.
Restricciones por origen
La autentificación por nombre de usuario y contraseña es sólo parte del cuento. Frecuentemente se desea permitir el acceso a los usuarios basandose en algo más que quiénes son. Algo como de dónde vienen.
Las directivas Allow y Deny posibilitan permitir y rechazar el acceso dependiendo del nombre o la dirección de la máquina que solicita un documento. La directiva Order va de la mano con estas dos, y le dice a Apache en qué orden aplicar los filtros.
El uso de estas directivas es:
Allow from address
donde address es una dirección IP (o una dirección IP parcial) o un nombre de dominio completamente cualificado (o un nombre de dominio parcial); puede proporcionar múltiples direcciones o nombres de dominio, si lo desea.
Por ejemplo, si usted tiene a alguien que manda mensajes no deseados a su foro, y quiere que no vuelva a acceder, podría hacer lo siguiente:
Deny from 205.252.46.165
Los visitantes que vengan de esa dirección no podrán ver el contenido afectado por esta directiva. Si, por el contrario, usted tiene un nombre de máquina pero no una dirección IP, también puede usarlo.
Deny from host.example.com
Y, si le gustaría bloquear el acceso de un dominio entero, puede especificar sólo parte de una dirección o nombre de dominio:
Deny from 192.101.205
Deny from cyberthugs.com moreidiots.com
Deny from ke
Usar Order le permitirá estar seguro de que efectivamente está restringiendo el acceso al grupo al que quiere permitir el acceso, combinando una directiva Deny y una Allow:
Order deny,allow
Deny from all
Allow from dev.example.com
Usando sólo la directiva Allow no haría lo que desea, porque le permitiría entrar a la gente proveniente de esa máquina, y adicionalmente a cualquier persona. Lo que usted quiere es dejar entrar sólo aquellos.
Conexiones seguras https
Instrucciones de instalación de apache con soporte ssl en Debian.
Primero creamos el directorio de certificados ssl con make /etc/apache2/ssl
Ejecutar el script apache2-ssl-certificate, el cual, una vez respondidas una serie de preguntas, generará el certificado ssl necesario para establecer conexiones https. Si en nuestra distribución no encontramos dicho script, ejecutariamos el comando make-ssl-cert /usr/share/ssl-cert/ssleay.cnf /etc/apache2/ssl/apache.pem, siguiendo luego las instrucciones que nos indique.
Luego, editando el archivo /etc/apache2/ports.conf añadiremos el siguiente parámetro:
Listen 443
Con lo cual establecemos que el apache escuche en el puerto destinado al protocolo https, el 443. Luego activamos el módulo ssl para apache con el domando:
a2enmod ssl
Creamos un archivo llamado, por ejemplo, ssl, en /etc/apache2/sites-enable, donde configuramos un dominio virtual cualquiera, que tiene que depender en todo caso de un NameVirtualHost *443 y al que le añadiremos los siguientes parámetros:
SSLEngine On
SSLCertificateFile /etc/apache2/ssl/apache.pem
Con estos parámetros activamos el uso de ssl para el dominio virtual que estamos configurando en el primero y en el segundo apuntamos al certificado ssl que utilizaremos para ese dominio (por si queremos usar diferentes certificados para diferentes dominios).
Por último, reiniciamos el apache para que todos los cambios sean efectivos.
Instalación y configuración de mod_security
Una vez instalado el módulo correspondiente a nuestra versión de Apache, editaremos el siguiente archivo:
vi /etc/httpd/conf.d/mod_security.conf
Y le daremos la siguiente configuración:
# Example configuration file for the mod_security Apache module
LoadModule security_module modules/mod_security.so
<IfModule mod_security.c>
# Turn the filtering engine On or Off
SecFilterEngine On
# The audit engine works independently and
# can be turned On of Off on the per-server or
# on the per-directory basis
SecAuditEngine RelevantOnly
# Make sure that URL encoding is valid
SecFilterCheckURLEncoding On
# Unicode encoding check
SecFilterCheckUnicodeEncoding On
# Only allow bytes from this range
SecFilterForceByteRange 1 255
# Cookie format checks.
SecFilterCheckCookieFormat On
# The name of the audit log file
SecAuditLog logs/audit_log
# Should mod_security inspect POST payloads
SecFilterScanPOST On
# Default action set
SecFilterDefaultAction "deny,log,status:406"
# Simple example filter
# SecFilter 111
# Prevent path traversal (..) attacks
# SecFilter "\.\./"
# Weaker XSS protection but allows common HTML tags
# SecFilter "<( |\n)*script"
# Prevent XSS atacks (HTML/Javascript injection)
# SecFilter "<(.|\n)+>"
# Very crude filters to prevent SQL injection attacks
# SecFilter "delete[[:space:]]+from"
# SecFilter "insert[[:space:]]+into"
# SecFilter "select.+from"
# Require HTTP_USER_AGENT and HTTP_HOST headers
SecFilterSelective "HTTP_USER_AGENT|HTTP_HOST" "^$"
# Only accept request encodings we know how to handle
# we exclude GET requests from this because some (automated)
# clients supply "text/html" as Content-Type
SecFilterSelective REQUEST_METHOD "!^GET$" chain
SecFilterSelective HTTP_Content-Type "!(^$|^application/x-www-form-urlencoded$|^multipart/form-data)"
# Require Content-Length to be provided with
# every POST request
SecFilterSelective REQUEST_METHOD "^POST$" chain
SecFilterSelective HTTP_Content-Length "^$"
# Don't accept transfer encodings we know we don't handle
# (and you don't need it anyway)
SecFilterSelective HTTP_Transfer-Encoding "!^$"
# Some common application-related rules from
# http://modsecrules.monkeydev.org/rules.php?safety=safe
#Nuke Bookmarks XSS
SecFilterSelective THE_REQUEST "/modules\.php\?name=Bookmarks\&file=(del_cat\&catname|del_mark\&markname|edit_cat\&catname|edit_cat\&catcomment|marks\&catname|uploadbookmarks\&category)=(<[[:space:]]*script|(http|https|ftp)\:/)"
#Nuke Bookmarks Marks.php SQL Injection Vulnerability
SecFilterSelective THE_REQUEST "modules\.php\?name=Bookmarks\&file=marks\&catname=.*\&category=.*/\*\*/(union|select|delete|insert)"
#PHPNuke general XSS attempt
#/modules.php?name=News&file=article&sid=1&optionbox=
SecFilterSelective THE_REQUEST "/modules\.php\?*name=<[[:space:]]*script"
# PHPNuke SQL injection attempt
SecFilterSelective THE_REQUEST "/modules\.php\?*name=Search*instory="
#phpnuke sql insertion
SecFilterSelective THE_REQUEST "/modules\.php*name=Forums.*file=viewtopic*/forum=.*\'/"
# WEB-PHP phpbb quick-reply.php arbitrary command attempt
SecFilterSelective THE_REQUEST "/quick-reply\.php" chain
SecFilter "phpbb_root_path="
#Topic Calendar Mod for phpBB Cross-Site Scripting Attack
SecFilterSelective THE_REQUEST "/calendar_scheduler\.php\?start=(<[[:space:]]*script|(http|https|ftp)\:/)"
# phpMyAdmin: Safe
#phpMyAdmin Export.PHP File Disclosure Vulnerability
SecFilterSelective SCRIPT_FILENAME "export\.php$" chain
SecFilterSelective ARG_what "\.\."
#phpMyAdmin path vln
SecFilterSelective REQUEST_URI "/css/phpmyadmin\.css\.php\?GLOBALS\[cfg\]\[ThemePath\]=/etc"
</IfModule>