Herramientas de fingerprinting web: como funcionan y cuanto ruido hacen

Unas de las herramientas más útiles para hacer una auditoría web son las de fingerprinting. Recopilan información que nos será de mucha ayuda en las fases posteriores de un pentest. Sin embargo, es posible que no nos hayamos parado a pensar que hacen estas herramientas por debajo, y que implicaciones puede tener utilizarlas contra la aplicación a auditar, en el sentido de si estaremos llamando demasiado la atención y si tal vez le haya llegado a alguien una alerta de tráfico sospechoso. Este post pretende mostrar “cuanto ruido hacen” estas aplicaciones y qué debemos tener en cuenta, en la perspectiva de un auditor que quiere evitar ser detectado, y en la perspectiva de un responsable de seguridad, cuya misión es detectar estos escaneos.

HTTPrint es una estupenda herramienta que te descubre las características del servidor web, aunque éste no devuelva ningún banner que informa del software en uso. Se basa en analizar el orden de las cabeceras de las respuestas HTTP, de los códigos de error cuando haces petición con un método no válido, versión de HTTP inexistente, o intentando usar un protocolo incorrecto. Los servidores web no responden de la misma manera a estas situaciones, y esto se puede aprovechar para reconocer el comportamiento de un servidor en concreto. Información detallada sobre estas técnicas se puede encontrar en el paper publicado por los mismos desarrolladores de HTTPrint.

Veamos que pasa cuando lanzamos el análisis sobre un servidor web. A continuación se muestra el access.log que ha generado el escaneo:

- - [15/Jan/2012:01:18:51 +0000] "\x16\x03" 501 301 "-" "-"
- - [15/Jan/2012:01:18:51 +0000] "GET / HTTP/1.0" 200 396 "-" "-"
- - [15/Jan/2012:01:18:52 +0000] "GET / HTTP/1.0" 200 396 "-" "-"
- - [15/Jan/2012:01:18:52 +0000] "OPTIONS * HTTP/1.0" 200 152 "-" "-"
- - [15/Jan/2012:01:18:52 +0000] "OPTIONS / HTTP/1.0" 200 204 "-" "-"
- - [15/Jan/2012:01:18:53 +0000] "GET /antidisestablishmentarianism HTTP/1.0" 404 520 "-" "-" - - [15/Jan/2012:01:18:53 +0000] "PUT / HTTP/1.0" 405 564 "-" "-"
- - [15/Jan/2012:01:18:53 +0000] "JUNKMETHOD / HTTP/1.0" 501 559 "-" "-"
- - [15/Jan/2012:01:18:53 +0000] "GET / JUNK/1.0" 200 396 "-" "-"
- - [15/Jan/2012:01:18:54 +0000] "get / http/1.0" 501 552 "-" "-"
- - [15/Jan/2012:01:18:54 +0000] "POST / HTTP/1.0" 200 396 "-" "-"
- - [15/Jan/2012:01:18:54 +0000] "GET /cgi-bin/ HTTP/1.0" 404 500 "-" "-"
- - [15/Jan/2012:01:18:55 +0000] "GET /scripts/ HTTP/1.0" 404 500 "-" "-"
- - [15/Jan/2012:01:18:55 +0000] "GET / HTTP/0.8" 200 396 "-" "-"
- - [15/Jan/2012:01:18:55 +0000] "GET / HTTP/0.9" 200 396 "-" "-"
- - [15/Jan/2012:01:18:56 +0000] "GET / HTTP/1.1" 200 396 "-" "-"
- - [15/Jan/2012:01:18:56 +0000] "GET / HTTP/1.2" 200 396 "-" "-"
- - [15/Jan/2012:01:18:56 +0000] "GET / HTTP/1.1" 400 518 "-" "-"
- - [15/Jan/2012:01:18:57 +0000] "GET / HTTP/1.2" 400 518 "-" "-"
- - [15/Jan/2012:01:18:57 +0000] "GET / HTTP/3.0" 200 396 "-" "-"
- - [15/Jan/2012:01:18:57 +0000] "GET /.asmx HTTP/1.1" 404 497 "-" "-"
- - [15/Jan/2012:01:18:58 +0000] "GET /../../ HTTP/1.0" 400 522 "-" "-"

Se puede observar las peticiones que hace, forzando al servidor a devolver un error concreto. A la vista de este log, se puede ver que la aplicación es bastante ruidosa, haciendo 22 peticiones bastante peculiares, cuyo administrador de la web podría detectar sin demasiado esfuerzo.

Destacar sobre todo la petición “GET /antidisestablishmentarianism HTTP/1.0”, palabra bastante peculiar que googleando rápidamente, descubro que es la palabra anglosajona más larga de su lengua. Detectando esta petición en nuestros logs podemos estar prácticamente seguros que nos han lanzado un HTTPrint a nuestros sistemas. De hecho, los chicos de Emerging Threads ya pensaron en esta idea y sacaron una regla para Snort que detecta escaneos con HTTPrint. Si generara una cadena aleatoria para utilizar este GET, el escaneo pasaría mucho más desapercibido. Una lástima que la aplicación no se actualice desde 2005.

Una forma de eludir los escaneos y obligarle a generar un resultado incorrecto es utilizar ModSecurity. Éste bloquearía las peticiones mal formadas y devolvería un error 400 genérico. HTTPrint no sabría interpretar estos resultados y abortaría el resto del escaneo. Se puede encontrar información detallada en el blog de ModSecurity.

WhatWeb es un script hecho en ruby y es realmente potente. La versión actual cuenta con 821 plugins, con las que reconoce los CMS más usuales. Vamos a probar contra un servidor de prueba www.pepito.com:

$ ./whatweb http://www.pepito.com http://www.pepito.com
[200] HTTPServer[Debian Linux][Apache/2.2.16 (Debian)], Apache[2.2.16], IP[111.111.111.111], PHP[5.3.3-7+squeeze1], X-Powered-By[PHP/5.3.3-7+squeeze1], Cookies[i%2Fpepito], Title[Pepito web!], Country[EUROPEAN UNION][EU]`

En un instante ya nos ha mostrado que el servidor web es un Apache sobre una Debian Squeeze, con PHP, etc. ¿Qué ha hecho realmente? veamos el access.log del Apache:

- - [15/Jan/2012:23:39:49 +0200] “GET / HTTP/1.1″ 200 4032 “-” “WhatWeb/0.4.7″`

Con solo una petición GET, ha sacado mucha información interesante del servidor Web. Aunque esto realmente no es nada del otro mundo. La web únicamente contenía el index por defecto del Apache. Haciendo una conexión con netcat se podría haber sacado la misma información sin mucho esfuerzo, observando los banners de respuesta de la petición HTTP. Probaremos ahora con otra web que tiene instalado un WordPress:

$ ./whatweb http://www.pepitowordpress.com www.pepitowordpress.com
[200] WordPress, HTTPServer[Debian Linux][Apache/2.2.16 (Debian)], x-pingback [www.pepitowordpress.com/xmlrpc.php], PoweredBy[WordPress,], UncommonHeaders[x-pingback,x-mobilized-by], Apache[2.2.16], IP[111.222.111.222], JQuery[1.7.1], PHP[5.3.8-1~dotdeb.2], X-Powered-By[PHP/5.3.8-1~dotdeb.2], Cookies[wpmp_switcher], Title[Pepito WordPress!], Country[UNITED STATES][US]

Se puede observar como ha sacado información adicional, identificando el WordPress. Veamos que peticiones ha hecho la herramienta contra el servidor:

- [17/Jan/2012:18:48:00 +0000] “GET /wordpress/ HTTP/1.1″ 200 70623 “-” “WhatWeb/0.4.7″`

Tan solo un GET. En este caso whatweb busca patrones, al encuentro de una coincidencia que le dé indicios de que se está usando una aplicación u otra. Esto incluye enlaces, nombres de carpeta, imágenes, ficheros php, etc. Incluso compara el md5 de ficheros concretos. En el caso del ejemplo, si encuentra un “Powered by WordPress”, la carpeta /wp-content/ típica de wordpress, y el md5 del favicon.ico coincide con el del wordpress, pues chico!, lo mismo es un wordpress! ;)

No obstante, el escaneo por defecto utiliza un user-agent muy identificativo, como podemos ver en los ficheros access.log anteriores. Por suerte, el script permite utilizar un user-agent personalizado. De esta forma, usando un user-agent de un navegador común, la posibilidad de detección de estos escaneos son prácticamente nulos.

La forma de defenderse contra estos escaneos, y burlar la capacidad de WhatWeb es (y perdonadme por el gatito muerto) “deswordpressizar” la web. Tratar de personalizar la aplicación el máximo posible para dificultar su reconocimiento. Para un atacante, conocer que una web es de un CMS y versión concreto puede facilitarle la tarea muchísimo, puesto que podría encontrar una vulnerabilidad conocida para este software y explotarla.

Es recomendable, por tanto:

  • Eliminar ficheros por defecto, readmes, favicons.
  • Modificar la estructura de directorio original, sustituirlo por algo personalizado.
  • Buscar cadenas que contengan el nombre del CMS, y eliminarlo si no es absolutamente necesario, como el caso del ejemplo anterior “Powered by…”
  • Limpiar los metas de contenido identificativo.
  • Ojito con los plugins. “WordPress superpowerfull plugin pack” y similares delatarían un cuidado y anónimo CMS.

Espero que os sea útil la lectura. Acepto comentarios, críticas y jamones \m/_

social