HTTP Fingerprinting

A continuación voy a citar un pequeño artículo realizado por David Carbajo Carralero en http://desistemas.net/2010/03/16/http-fingerprinting. El artículo, aun siendo muy sencillo, nos puede ser útil para ver la importancia de cuidar al máximo la información que ofrecen nuestros servidores.

Fingerprint, ¿Qué es? ¿Para qué sirve?

fingerprint En el caso de un criminalista forense, las huellas dactilares son marcas que quedan impresas en las superficies cuando alguien las toca e identifican inequívocamente a un sujeto. Para nosotros son algo un poco distinto.
Una huella, fingerprint, o como prefieras llamarla no es mas que una respuesta de “alguien”, llamémoslo destino, ante una petición determinada.
Nosotros <—– Comunicación —–> Destino

Analizando esas respuestas y comparándolas con unos patrones podríamos deducir qué tipo de servicio, sistema operativo, etc. esta del otro lado.

Ejemplo:
Petición
HEAD / HTTP/1.1 host: www.unaweb.org 
en el puerto 80.

Respuesta:
HTTP/1.1 200 OK
Date Mon, 20 Oct 2008 20:42:27 GMT
Server: Apache
X-Powered-By: PHP/4.3.9
….
Dado que las técnicas de fingerprinting no son mas que un análisis de respuestas, entonces podemos aplicarlas a prácticamente cualquier servicio que tenga interacción con el cliente como por ejemplo ftp, telnet, http, etc.

Si por ejemplo hacemos:
david@sat:~$ ftp ftp.yyyy.es
Connected to xxx.yyyy.es
220-Welcome to Pure-FTPd
Name (ftp.yyyy.es:david): anonymous
Password:
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> 

Ya tenemos algo de información. Eso, a groso modo, es una huella:

Una respuesta que da información. A veces este tipo de respuestas no aportan por si solas los datos suficientes para llegar a una conclusión, pero sí nos van marcando un camino. La clave aquí reside en diversificar y buscar por diferentes vías para poder contrastar la información obtenida. Hay que pensar que todo es susceptible de ser modificado para proporcionar una respuesta diferente a lo que debería ser, pero esto lo veremos mas adelante.

Quizá el fingerprinting mas famoso es el TCP/IP stack fingerprinting. Es lo que hace la opción -O implementada en nmap. Básicamente esta técnica consiste en jugar con el TCP/IP sabiendo como reaccionan los distintos Sistemas Operativos ante diferentes paquetes, valores de campos, etc.

(Mas información en http://nmap.org/book/osdetect.html)

HTTP Fingerprinting, HTTP y otras cosas raras

Las técnicas que se ocupan del análisis de las respuestas de los servidores web reciben el nombre de http fingerprinting. El propósito de estas no es, como en el caso del TCP/IP stack fingerprinting, averiguar el sistema operativo remoto, sino identificar los servidores HTTP que están prestando el servicio en el otro extremo de la conexión.



Como ya se sabe, los servidores web se entienden con los clientes a través de un protocolo llamado Hypertext Transfer Protocol (HTTP). HTTP es un protocolo a nivel de aplicación que lleva funcionando desde 1990. La primera versión, muy simple, fue la 0.9. En la primera mitad de los años 90 apareció la 1.0 (http://www.ietf.org/rfc/rfc1945.txt) con bastantes mejoras para dar paso en 1999 a la versión 1.1 (http://www.ietf.org/rfc/rfc2616.txt).



Estaría bien leer un poco el RFC de HTTP/1.1 (http://www.ietf.org/rfc/rfc2616.txt), mas que nada para tener una visión global de todo y hacernos una idea de su funcionamiento. De todas maneras, como la lectura es un tanto espesa vamos a extraer lo más importante para tener una idea de la sintaxis básica de HTTP/1.1.

Las peticiones mas importantes son: GET, HEAD, DELETE y OPTIONS.


Sintaxis de los métodos GET, HEAD, DELETE y OPTIONS

Para comprender el funcionamiento de estos métodos vamos a ver unos cuantos ejemplos prácticos.


GET
Sintaxis: GET Request-URI PROTOCOL

El metodo GET ataca a cualquier información que se le pasa como argumento en Request-URI. Es una forma de “pedir” un archivo. Al hacer:
GET /pub/index.htm HTTP/1.1

Le estamos indicando al servidor que queremos el archivo /pub/index.htm y que empleamos el protocolo HTTP/1.1.

Un ejemplo práctico:
Petición:
david@sat:~$ telnet www.xxxx.com 80
Trying 22.22.22.22…
Connected to www.xxxx.com.
Escape character is ‘^]’. 
GET / HTTP/1.1
host: www.xxxx.com [ENTER][ENTER] 

 Respuesta:
HTTP/1.1 200 OK
Date: Tue, 21 Oct 2008 14:28:57 GMT
Server: Apache
X-Powered-By: PHP/4.3.9
Set-Cookie: PHPSESSID=ba7421d0b10bf48fb6d3c9e6fd79ca67; path=/
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, 
pre-check=0
Pragma: no-cache
Connection: close
Transfer-Encoding: chunked
Content-Type: text/html; charset=ISO-8859-1
 
2000
<!DOCTYPE HTML PUBLIC-//W3C//DTD HTML 4.01 Transitional//EN
http://www.w3.org/TR/html4/loose.dtd>
<html>
….. 
</html>
 
0
 
Connection closed by foreign host. 
david@sat:~$ 

Tras escribir la línea host: www.xxxx.com deberemos pulsar dos veces enter. La primera para indicarle el fin de la línea de petición (la de host: www.xxxx.com) y la segunda para indicarle el fin de las cabeceras opcionales.

Cuando en Request-URI ponemos / quiere decir que lo que queremos es el archivo index del directorio raíz.

En HTTP/1.0 bastaba con hacer un GET / HTTP/1.0, sin embargo desde la versión 1.1 hay que identificar el nombre de host. Esto tiene una explicación: Virtual Hosts.

 

Supongamos que tenemos una IP: 22.22.22.22 y dos nombres que apuntan a esa IP: www.xxxx.org y www.yyyy.org. Bien, en HTTP/1.1 al indicar el nombre del host el servidor es capaz de devolver un contenido diferente dependiendo de cual sea la petición. Es lo que se conoce como Virtual Hosts.

Nota: Existe una alternativa a indicar el nombre de máquina en la línea de cabecera host: Hacer el GET de la ruta completa al archivo indicando en la misma el nombre de máquina. Quiero puntualizar que aquí solo trato de dar unas pautas generales para que luego cada uno se lo cocine al gusto.

HEAD

Sintaxis: HEAD Request-Uri PROTOCOL

El método HEAD es idéntico a GET excepto porque porque el servidor no devuelve el contenido del archivo solicitado sino tan solo las cabeceras.

Petición:
david@sat:~$ telnet www.xxxx.com 80
Trying 22.22.22.22…
Connected to www.xxxx.com.
Escape character is ‘^]’.
HEAD / HTTP/1.1
host:www.xxxx.com

Respuesta: 
HTTP/1.1 200 OK
Date: Tue, 21 Oct 2008 14:22:05 GMT
Server: Apache
X-Powered-By: PHP/4.3.9
Set-Cookie: PHPSESSID=cac08aaaa0b49abea7e499cbe9d742dd; path=/
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0,
pre-check=0
Pragma: no-cache
Connection: close
Content-Type: text/html; charset=ISO-8859-1


DELETE
Sintaxis: DELETE Request-URI PROTOCOL

Con este método le indicamos al servidor que debe borrar el archivo indicado en Request-URI. Lo normal por supuesto es que nos de un error del tipo 405: Method Not Allowed, 403: Forbidden o similar. Dependiendo del servidor http.

Petición:
david@sat:~$ telnet www.xxxx.com 80
Trying 22.22.22.22…
Connected to www.xxxx.com.
Escape character is ‘^]’.
DELETE / HTTP/1.1
host:www.xxxx.com

Respuesta:
DELETE / HTTP/1.0
HTTP/1.1 405 Method Not Allowed
Date: Tue, 21 Oct 2008 19:49:48 GMT
Server: Apache
Vary: accept-language,accept-charset
……


OPTIONS

Sintaxis: OPTIONS Request-URI PROTOCOL

Con este método pedimos información sobre los métodos permitidos para la petición/respuesta identificada por Request-URI.

OPTIONS permite utilizar un asterisco (*) como Request-URI. Cuando lo utilizamos se nos responde con los métodos permitidos en el servidor.

Petición:
david@sat:~$ telnet www.xxxx.com 80
Trying 22.22.22.22…
Connected to www.xxxx.com.
Escape character is ‘^]’.
OPTIONS * HTTP/1.1
host: www.xxxx.com

Respuesta: 
HTTP/1.1 200 OK
Date: Tue, 21 Oct 2008 15:25:51 GMT
Server: Apache
Allow: GET,HEAD,POST,OPTIONS,TRACE
Content-Length: 0
Connection: close
Content-Type: text/plain; charset=ISO-8859-1
 
Connection closed by foreign host.
david@sat:~$

Aunque hay mas métodos, GET, HEAD, DELETE y OPTIONS son, como ya he dicho anteriormente los mas usados dentro del http fingerprinting. Se quedan en el tintero POST, PUT, TRACE y CONNECT que también tienen mucho juego.


En el otro lado del cable

Como ya se pudo observar, las respuestas por parte del servidor que hemos visto en el apartado anterior siempre comenzaban por algo así:
HTTP/1.1 200 OK

En general la sintaxis podría ser como sigue:
PROTOCOL STATUS_CODE METAINFORMATION

¿Qué significa esto?. Bien, con esta línea el servidor nos indica si la petición del cliente se ha realizado con éxito o no y porque. En un primer lugar se especifica la versión del protocolo con la que estamos trabajando (PROTOCOL), a continuación aparece el STATUS_CODE o código de estado que consiste en tres  dígitos que nos indican el resultado de la petición efectuada y por último encontramos la metainformación (METAINFORMATION), es decir, una pequeña información sobre la respuesta devuelta por el servidor.

Los códigos de estado pueden agruparse en cinco bloques:
  • 100 – 199: De Información.
  • 200 – 299: Petición del cliente procesada correctamente. Recibida,
    entendida y aceptada.
  • 300 – 399: Petición del cliente redireccionada.
  • 400 – 499: Error en la Peticion del cliente.
  • 499 – 599: Error en Servidor. Se produce cuando el servidor falla y es incapaz de realizar alguna petición.
El esquema de todos los códigos de estado es el siguiente:
  • 1XX – Informational
  • 100 Continue
  • 101 Switching Protocols
  • 2XX – Succeful
  • 200 OK
  • 201 Created
  • 202 Accepted
  • 203 Non-Authoritative Information
  • 204 No Content
  • 205 Reset Content
  • 206 Partial Content
  • 3XX – Redirection
  • 300 Multiple Choices
  • 301 Moved Permanently
  • 302 Found
  • 303 See Other
  • 304 Not Modified
  • 305 Use Proxy
  • 306 (Unused)
  • 307 Termorary Redirect
  • 4XX – Client Error
  • 400 Bad Request
  • 401 Unauthorized
  • 402 Payment Required
  • 403 Forbidden
  • 404 Not Found
  • 405 Method Not Allowed
  • 406 Not Acceptable
  • 407 Proxy Authentication Required
  • 408 Request Timeout
  • 409 Conflict
  • 410 Gone
  • 411 Leght Required
  • 412 Precondition Failed
  • 413 Request Entity Too Large
  • 414 Request-URI Too Long
  • 415 Unsupported Media Type
  • 416 Requested Range Not Satisfiable
  • 417 Expectation Failed
  • 5XX – Server Error
  • 500 Internal Server Error
  • 501 Not Implemented
  • 502 Bad Gateway
  • 503 Service Unavaiable
  • 504 gateway Timeout
  • 505 HTTP Version Not Supported
Técnicas de http fingerprinting

Como ya hemos visto anteriormente, el http fingerprinting consiste en adivinar que servidor web esta corriendo mediante el análisis de las respuestas que este nos devuelve.

Quizá el primer esbozo de estas técnicas aparece con la famosa cabecera Server. Es lo que se conoce como banner string. A continuación un par de  ejemplos:

Petición:
david@sat:~$ telnet www.xxxx.com 80
HEAD / HTTP/1.1
host: www.xxxx.com

Respuesta:
HTTP/1.1 200 OK
Date: Wed, 22 Oct 2008 10:44:15 GMT
Server: Apache
X-Powered-By: PHP/4.3.9
…..

Petición:
david@sat:~$ telnet www.xxxx.net 80
HEAD / HTTP/1.1
host: www.xxxx.net

Respuesta:
HTTP/1.1 200 OK
Cache-Control: private
Content-Length: 52034
Content-Type: text/html; charset=utf-8
Server: Microsoft-IIS/7.0
Set-Cookie:
 
CSAnonymous=QzAXvh01yQEkAAAAZjNiZjlmMWItZGVhMi00NjFiLTgzNjEtZTljOWY2YzljYzlj0;
domain=xxxx.net; expires=Thu, 23-Oct-2008 14:43:41 GMT; path=/; HttpOnly
…..

En el primer ejemplo tenemos un Apache (http://www.apache.org) mientras que en el segundo caso se trata de un Internet Information Server de Microsoft (http://www.iis.net). Todo esto es una suposición. ¿Por qué? simplemente porque es bastante fácil modificar el servidor web para que oculte o cambie esta cabecera. En Apache, por ejemplo, existe httpd.conf y mod_security para poder cambiar la identidad del mismo.

Si nos fijamos en las respuestas de los servidores web veremos que, además del campo Server, existen numerosas diferencias como por ejemplo:
  • Orden de las cabeceras.
  • Palabras utilizadas para el contenido de las cabeceras.
  • Uso de mayusculas y minisculas.
  • Cabeceras especificas.
  • etc.
Bien, todo esto es lo que constituye la  base del http fingerprinting.


Ejemplos y recursos

El siguiente paso es tener (o crear) alguna relación de las diferencias que hay entre los distintos servidores. Httprecon (http://www.computec.ch/projekte/httprecon) es un proyecto que se dedica a investigar sobre este campo. Tienen una base de datos bastante completa (http://www.computec.ch/projekte/httprecon/?s=database)  con mas de 320 entradas. En ella se puede navegar por las distintas peticiones (GET, HEAD, DELETE, OPTIONS y TEST) y ver que contenido y orden tienen las cabeceras de respuesta de cada servidor ante la petición formulada.

Por ejemplo, para el primer caso: GET EXISTING.

Como se nos indica en la web consiste en hacer un GET de un recurso existente. Por ejemplo podría ser GET / HTTP/1.1. Si pinchamos en el método aparecerá un listado con todas las cabeceras posibles y sus valores correspondientes según el servidor que responda.

Vamos a ver un par de casos prácticos:

Petición:
david@sat:~$ telnet www.xxxx.com 80
Trying 22.22.22.22…
Connected to 22.22.22.22.
Escape character is ‘^]’.
HEAD / HTTP/1.1
host: www.xxxx.com

Respuesta:
HTTP/1.1 200 OK
Content-Length: 600
Content-Type: text/html
Content-Location: http://www.xxxx.com/Default.htm
Last-Modified: Thu, 13 Oct 2005 07:14:52 GMT
Accept-Ranges: bytes
ETag: “07ee8cdc5cfc51:ec2″
Server: Unknown
X-Powered-By: ASP.NET
Date: Thu, 23 Oct 2008 09:08:15 GMT
 
 
Connection closed by foreign host.
david@sat:~$

El método empleado es un HEAD sobre un recurso existente. En httprecon podemos consultar la entrada de la base de datos correspondiente.
  • En este caso la cabecera “Server” no nos aporta información.
  • Lo primero es consultar el orden de las cabeceras. En este caso solo hay un candidato que presenta las cabeceras en ese orden:
a) Microsoft IIS 6.0
  • Si prestamos atención a los valores de las cabeceras Content-Type, Accept-Ranges y X-Powered by podremos comprobar que en efecto se trata de MS-IIS/6.0.
  • Dado que IIS 7.0 es la nueva versión que Microsoft saco para los sistemas Windows server 2008, todo indica que se trata de un Windows 2003.
Vamos con otro ejemplo:

Sabemos que en la IP 3.3.3.3 hay un router.

Petición:
david@sat:~$ telnet 3.3.3.3 80
Trying 3.3.3.3…
Connected to 3.3.3.3.
Escape character is ‘^]’.
HEAD / HTTP/1.1
host: 3.3.3.3

Respuesta:
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Basic realm=”P-660HW-D1″
Content-Type: text/html
Transfer-Encoding: chunked
Server: RomPager/4.07 UPnP/1.0
Connection: close
EXT:
 
083
<html>
<head>
<title>Protected Object</title></head><body>
<h1>Protected Object</h1>This object on the RomPager server is protected
0
 
Connection closed by foreign host.
david@sat:~$

En este caso el método empleado es un HEAD sobre un recurso existente. Consultamos la base de datos.
  • Según la cabecera “Server” se trata de un router ZyXEL. En cuanto a  la version del servidor web, mirando el orden de las cabeceras hay tres  opciones:
a) ZyXEL ZyWALL 10W RomPager 4.07. 
b) ZyXEL Prestige 662H-61 RomPager 4.07.
c) ZyXEL Prestige 662H-63/67 RomPager 4.07.

En algunas ocasiones se nos presentara una situación en la que nos quedamos con dos o tres candidatos y no hay diferencias documentadas entre los mismos. Aunque las técnicas empleadas no sean una ciencia exacta si pueden ser muy útiles para guiar al intruso potencial en su recopilación de información.

En este caso, teniendo en cuenta lo que dice la cabecera WWW-Authenticate, el país (España) y que telefónica ha vendido ese modelo de router a diestro y siniestro probablemente no cueste demasiado llegar a la conclusión de que tenemos un router P660HW.

Lógicamente es imposible conocer de memoria todas las diferencias entre los servidores web, y, a veces, consultar las bases de datos puede hacerse eterno.

Todo este proceso (al igual que ocurre con el TCP/IP stack fingerprinting) está automatizado en programas como httprecon (http://www.computec.ch/projekte/httprecon/?s=download), httprint (http://net-square.com/httprint/#downloads) y muchos mas. Aquí entra en juego el gusto y las preferencias de cada uno.


Defensa

¿Qué hacer para defendernos de estas técnicas?

Para ponerlo un poco mas difícil se podrían tomar algunas medidas, como por ejemplo cambiar el campo Server, el orden y contenido de las cabeceras, etc.. La idea es modificar el servidor web para que cambie algunas respuestas y así sea mas complicada la identificación. En Apache, por ejemplo, podemos utilizar mod_security (http://www.modsecurity.org) para hacer algunas modificaciones.

Para Microsoft IIS tenemos disponible ServerMask (http://www.iis.net/downloads/default.aspx?tabid=34&g=6&i=1268), desarrollado por port80software.

Podríamos decir que estas técnicas siguen el principio de lo que se conoce como Security by obscurity, es decir, algo así como conseguir que sea mas seguro evitando que alguien de fuera pueda saber que es exactamente lo que esta al otro lado.


Artículo original publicado por David Carbajo Carralero, Alicante, 2010 (http://desistemas.net/2010/03/16/http-fingerprinting/)

Entradas populares de este blog

Trinity Rescue Kit: Tutorial para eliminar la contraseña de administrador en Windows

Cómo extraer el handshake WPA/WPA2 de archivos de captura grandes