21 noviembre 2011

Fortificación de lighttpd

Lighttpd es otro servidor web libre y gratuito que está desarrollado con el objetivo de ser ligero y altamente eficaz.

Al igual que la semana pasada con nginx, vamos a repasar algunas directivas que pueden impactar en la seguridad y que se han de tener en cuenta en una instalación o auditoría.

Lo primero y más básico es arrancar el servicio con un usuario no privilegiado, por lo que el fichero de configuración ha de incluir dos lineas como las siguientes:

server.username = "lighttpd" 
server.groupname = "lighttpd"

Para evitar que se generen listas del contenido de un directorio en caso de no existir un archivo index.html, es necesario deshabilitar el parámetro dir-listing tal de la siguiente forma:

dir-listing.activate = "disabled" 

Para modificar la cabecera Server y no mostrar la versión y producto del servidor web se especifica la cadena en server.tag:

server.tag ="HTTPD"

Si se desea restringir el acceso a determinadas extensiones de ficheros, que pueden existir residualmente o ser de configuración, puede hacerse como en este ejemplo:

url.access-deny = ( "~", ".inc", ".bak" )

Si el servidor no va a recibir ficheros, también se puede limitar el tamaño de una petición a 1kb, 

server.max-request-size  = 1

TRACE y TRACK, no están soportados en lighttpd, pero para deshabilitar todos los métodos menos los esencialmente necesarios como son GET, HEAD y POST:

$HTTP["request-method"] !~ "^(GET|HEAD|POST)" {
url.access-deny = ( "" )
}

Si queremos molestar a los auditores y denegar el acceso a algunas herramientas automáticas en base a su user-agent, se puede hacer con una expresión regular. ¡Ojo!, que esto es fácilmente evadible y sirva más de ejemplo para evitar bots o ataques concretos.

$HTTP["useragent"] =~ "(acunetix|nikto)" {
url.access-deny = ( "" )
}

Para evitar que las imágenes del servidor sean enlazadas desde otro sitio (hotlinking), tan solo hay que añadir las siguientes líneas:

$HTTP["referer"] !~ "^(hxxp://sbd\.com|hxxp://www\.sbd\.com)" {
url.access-deny = ( ".jpg", ".jpeg", ".png", ".gif" )
}

El status es un módulo que muestra información sobre el servidor, en ocasiones estos datos pueden incluir datos confidenciales y debería estar restringido a direcciones IP. Si no se utiliza, es aconsejable eliminarlo, borrando la línea que contenga "status.status-url" y verificando que no está cargado en "server.modules"

status.status-url = "/server-status"
server.modules = ( ..., "mod_status", ... )

Por último, si se hace uso de SSL, es recomendable deshabilitar la v2 y algunos ciphers. Una configuración robusta (a falta de parche para BEAST) podría ser esta:

ssl.use-sslv2 = "disable"
ssl.cipher-list = "TLSv1+HIGH !SSLv2 RC4+MEDIUM !aNULL !eNULL !3DES @STRENGTH"

Para restringir un recurso a varias direcciones IP, rangos o localhost, lighthttpd permite este tipo de sintaxis:

$HTTP["remoteip"] !~ "192.168.1.3|10.0.5.*|127.0.0.1" { 
   $HTTP["url"] =~ "^/Admin/" { url.access-deny = ( "" ) }
}

En caso de querer proteger un directorio con usuario y contraseña, del RFC 2617 se ha de usar digest y nunca basic, con una sintaxis del módulo mod_auth, similar a la siguiente

auth.backend = "htdigest"
auth.backend.htdigest.userfile = "lighttpd-htdigest.user" 
auth.debug = 2

auth.require = ( "/protected/" =>
    (
    "method"  => "digest",
    "realm"   => "Nombre de mi directorio con Password",
    "require" => "valid-user"
    ),
)
Para crear el fichero lighttpd-htdigest.user:
# htdigest -c lighttpd-htdigest.user 'Nombre de mi directorio con Password' aramosf

3 comments :

juino dijo...

Me lo guardo, que nunca se sabe cuando puede venir bien. Muy buenas recomendaciones :)

Busindre dijo...

Falta una R, foti foti :D

Alejandro Ramos dijo...

Gracias!, ya lo he cambiado, he tardado un buen rato en saber que decías XD