
En el ámbito de la ciberseguridad, identificar y caracterizar con precisión los servidores web es crucial para la detección de amenazas, la evaluación de vulnerabilidades y el mapeo de redes. Presentamos HTTP-Basma, un novedoso algoritmo de fingerprinting activo que revela perfiles únicos de servidores mediante un enfoque multicapa.
HTTP-Basma está disponible en https://httpbasma.netomize.ca/
En el ámbito de la ciberseguridad, identificar y caracterizar con precisión los servidores web es crucial para la detección de amenazas, la evaluación de vulnerabilidades y el mapeo de redes. Presentamos HTTP-Basma, un novedoso algoritmo de fingerprinting activo que revela perfiles únicos de servidores mediante un enfoque multicapa, abordando así este desafío.
Características clave: Solicitudes Diseñadas, Respuestas Reveladoras: HTTP-Basma envía 8 sondas HTTP meticulosamente diseñadas, provocando respuestas distintivas que reflejan las configuraciones del servidor. Doble Hash para Versatilidad. El algoritmo genera dos hashes:
Agrupación y Caza: Estos hashes permiten la agrupación de servidores, la identificación de servidores únicos y similares, y la búsqueda de actores maliciosos con mayor confianza.
Diseño Modular para Expansión: La arquitectura del algoritmo fomenta la adición de nuevas variantes de hash, alentando la colaboración y la adaptabilidad.
En este documento, primero revisamos los trabajos existentes notables sobre fingerprinting HTTP y luego exploramos la funcionalidad, el diseño, la arquitectura y los resultados del algoritmo. Además, mostraremos hallazgos convincentes del escaneo del top 1 millón de sitios web de Majestic, incluida la identificación y agrupación de servidores HTTP C&C para varias familias de malware.
La idea central del algoritmo de HTTP-Basma se centra en enviar 8 solicitudes HTTP especialmente diseñadas con requisitos variables para provocar diferentes respuestas del servidor. Una vez recuperada la respuesta del servidor, la línea de estado HTTP se disecciona quirúrgicamente para todos sus elementos y se codifica de manera óptima. Además, se verifica la codificación de ciertos encabezados seleccionados de la respuesta del servidor.
Las solicitudes que envía son de estos tipos:
Después de cada solicitud, se analiza la respuesta del servidor para extraer encabezados específicos y sus valores. Estos datos extraídos se someten a un procesamiento adicional, incluida la disección y codificación, para generar una huella digital reversible.
Los detalles técnicos completos de cómo funciona el algoritmo se encuentran en el documento adjunto.
Esta filosofía de diseño modular trata cada huella digital de solicitud como un bloque de construcción, lo que permite una refactorización elegante, con la posibilidad de agregar y restar la huella digital de cualquier solicitud.
Muestra de huellas digitales:
- fp verbosus: 011420958a0014514bd5221420958a221420958a221420958a2200001420958a22000000001f
- fp pacto: 02464ae8b7d86f82c9918e2c2b9d6b91
- nota: tasa de falsos positivos (72/986,910)
- fp verbosus: 01142494d60914514bd522142494d6221420958a701420958a220000140e04922032c37f1609
- fp pacto: 020769322f3d94ac2f258ddf5ce08502
- nota-1: tasa de falsos positivos 0
- nota-2: tevedadav.site/43.209.165.126:443 (TLS)
- muestra-(sha-256): 9aa1dec8dd12f8adc7fc1274e1958f3613450109ee8b4ec6442a0fcf06df0972
- fp verbosus: 01140a85e40014512f3612140a85e422140a85e422140a85e4220000140a85e4220000000001
- fp pacto: 0207292309a7a7e798e417d69df5f2a5
- nota: tasa de falsos positivos (73/986,910)
- fp verbosus: 01140a85e4001320958a22142494d62214254c5e2214254c5e22080014254c5e220000000000
- fp pacto: 0202be780e1eaae0eaa6184e20c909b6
- nota: tasa de falsos positivos (4/986,910)
- fp verbosus: 01140a85e4011320958a22142494d67214254c5e2214254c5e22080014254c5e220000000000
- fp pacto: 02cc5be6d05192e17de041538508bc22
- nota: tasa de falsos positivos (38/986,910)
- fp verbosus: 01140a85e40914514bd522140a85e4721420958a701420958a220800140a85e4720000001609
- fp pacto: 0221b4e46bbd0e5c037f5a852ca3fdc0
- nota: tasa de falsos positivos (6/986,910)
HTTP-Basma es una herramienta en C++ que desarrollé para demostrar la practicidad y viabilidad de este algoritmo. Aprovecha la biblioteca de Chilkat para todas las interacciones de sockets HTTP y utiliza otras clases de soporte dentro de la biblioteca. Además, la herramienta incluye una función de demangling que puede diseccionar e invertir el hash difuso verbosus, generando un objeto JSON completo, y una función comparadora que muestra las diferencias entre dos huellas digitales verbosus.
Tenga en cuenta que algunas salidas de la herramienta pueden usar números de sonda ligeramente diferentes, pero el orden subyacente permanece consistente: P1->P1, P2->P2, P3->P3, P4->P4, P->P5, P6->P6F, P7->P6L, P8->P7a.
Uso:
HTTP-Basma [OPCIÓN...]
-d, --domain arg dominios/IPs (puede consultar múltiples dominios, separados por comas)
-p, --port arg número de puerto
-s, --ssl ¿la conexión HTTP debe realizarse a través de SSL/TLS?
-q, --qpath verificar dominio con la ruta URL incluida (no recomendado)
-w, --redirect habilitar/deshabilitar redirecciones HTTP. Si está deshabilitado/falso, solo se sigue la siguiente redirección;
de lo contrario, se siguen todas las redirecciones (predeterminado: true)
-t, --ctimeout arg valor de tiempo de espera de conexión del socket en segundos (predeterminado: 1)
-g, --rtimeout arg valor de tiempo de espera de lectura del socket (del servidor) en segundos (predeterminado: 1)
-e, --sleep arg la duración (en milisegundos) para pausar entre cada solicitud (predeterminado: 100)
-x, --proxy arg configuración del proxy: <"socks4|socks5|http">,<dominio>,<puerto>,<bool:direct_tls>,<login>,<pass>
todos los valores están separados por comas. <direct_tls> se ignora con un proxy no HTTP
-f, --file arg archivo con lista de dominios/IPs (requiere "-c/--csv" o "-j/--json")
-P, --parallel Escanear la lista de dominios pasada mediante la opción "-f/--file" en paralelo
-c, --csv guardar en archivo csv; si no se especifica la opción 'n', el nombre del archivo CSV se generará
automáticamente
-n, --csvfile arg nombre del archivo CSV
-j, --json guardar en archivo json; si no se especifica la opción 'l', el nombre del archivo JSON se generará
automáticamente
-l, --jsonfile arg nombre del archivo JSON
-r, --saveh guardar encabezados de respuesta de solicitudes
-o, --pjson mostrar la disección de la huella digital en la consola como un objeto JSON
-i, --demangle_json arg desenmarañar una huella digital en un formato json detallado (puede tener más de una, separadas
por comas)
-u, --demangle_txt arg generar un formato de texto conciso de la huella digital, separado por comas para múltiples resultados
-C, --compare arg comparar dos huellas digitales verbosus (separadas por comas)
-a, --pacto arg obtener la huella digital Pacto usando Verbosus
-h, --help imprimir uso
Al solicitar un dominio/IP determinado, la respuesta se puede guardar en un archivo CSV o JSON con una gran cantidad de información sobre los encabezados de respuesta del servidor y la huella digital única de cada sonda.
Por ejemplo, para obtener la huella digital del servidor https://google.com y guardar los resultados en un archivo JSON y CSV, mientras se guardan los encabezados de respuesta HTTP de cada sonda:
HTTPBasma.exe -d https://google.com --json --csv --saveh
En la carpeta Output, encontrará el archivo CSV google_hb_results_2026-05-19_08-35-38_am.csv y el archivo JSON google_hb_results_2026-05-19_08-35-38_am.json.
La función demangler de la herramienta "-i/--demangle_json" toma una huella digital verbosus y reconstruye los atributos de cada sonda, generando un objeto JSON completo. En particular, al intentar invertir los hashes FNV-1a, el demangler utiliza dos bases de datos locales: options.csv para los métodos HTTP permitidos y status_line_db.csv para las frases de razón de la línea de estado. Si falta alguno de estos archivos de base de datos, la función correspondiente de inversión de hash se deshabilita automáticamente. Estas bases de datos se compilaron a partir de un escaneo del top 1 millón de sitios web de Majestic.
El demangling de la huella digital de verbosus, para el dominio example.com:
HTTPBasma.exe --demangle_json 01140a85e40014514bd522142494d67214254c5e721420958a22020214254c5e720000001609
{
"type": "verbosus",
"fp": "01140a85e40014514bd522142494d67214254c5e721420958a22020214254c5e720000001609",
"p1": {
"type": "get_normal",
"fp": "140a85e400",
"status_line": {
"http_version": {
"fp": "14",
"val_cmt": "HTTP/1.1"
},
"status_code": {
"fp": "0a",
"val_cmt": "200"
},
"http_reason": {
"fp": "85e4",
"val_cmt": "OK"
},
"sl_reversed_db": {
"http_version": "HTTP/1.1",
"status_code": [
200,
404,
403,
500,
204,
999,
888,
603
],
"http_reason": "OK"
}
},
"sts_hdr": {
"fp": "00",
"cmt": "este encabezado no se utiliza"
}
},
"p2": {
"type": "get_invalid_ver_nb",
"fp": "14514bd522",
"status_line": {
"http_version": {
"fp": "14",
"val_cmt": "HTTP/1.1"
},
"status_code": {
"fp": "51",
"val_cmt": "505"
},
"http_reason": {
"fp": "4bd5",
"val_cmt": "HTTP Version Not Supported"
},
"sl_reversed_db": {
"http_version": "HTTP/1.1",
"status_code": [
505
],
"http_reason": "HTTP Version Not Supported"
}
},
"cont_len_hdr": {
"fp": "22",
"name": "Content-Length",
"value": ">1",
"cmt": "el encabezado content-length/transfer-encoding:chunked está presente con cualquiera de los valores de tamaño: [0,1,>1]"
},
"cnx": {
"ka": false,
"c": true
}
},
"p3": {
"type": "get_rnd_resource",
"fp": "142494d672",
"status_line": {
"http_version": {
"fp": "14",
"val_cmt": "HTTP/1.1"
},
"status_code": {
"fp": "24",
"val_cmt": "404"
},
"http_reason": {
"fp": "94d6",
"val_cmt": "Not Found"
},
"sl_reversed_db": {
"http_version": "HTTP/1.1",
"status_code": [
404,
403,
501,
410,
204,
400,
200,
418
],
"http_reason": "Not Found"
}
},
"cont_len_hdr": {
"fp": "72",
"name": "Transfer-Encoding",
"value": ">1",
"cmt": "el encabezado content-length/transfer-encoding:chunked está presente con cualquiera de los valores de tamaño: [0,1,>1]"
},
"cnx": {
"ka": true,
"c": false
}
},
"p4": {
"type": "get_rnd_verb",
"fp": "14254c5e72",
"status_line": {
"http_version": {
"fp": "14",
"val_cmt": "HTTP/1.1"
},
"status_code": {
"fp": "25",
"val_cmt": "405"
},
"http_reason": {
"fp": "4c5e",
"val_cmt": "Method Not Allowed"
},
"sl_reversed_db": {
"http_version": "HTTP/1.1",
"status_code": [
405,
403,
204,
418,
404
],
"http_reason": "Method Not Allowed"
}
},
"cont_len_hdr": {
"fp": "72",
"name": "Transfer-Encoding",
"value": ">1",
"cmt": "el encabezado content-length/transfer-encoding:chunked está presente con cualquiera de los valores de tamaño: [0,1,>1]"
},
"cnx": {
"ka": true,
"c": false
}
},
"p5": {
"type": "get_lowercase_verb",
"fp": "1420958a22",
"status_line": {
"http_version": {
"fp": "14",
"val_cmt": "HTTP/1.1"
},
"status_code": {
"fp": "20",
"val_cmt": "400"
},
"http_reason": {
"fp": "958a",
"val_cmt": "Bad Request"
},
"sl_reversed_db": {
"http_version": "HTTP/1.1",
"status_code": [
400,
422,
405,
401
],
"http_reason": "Bad Request"
}
},
"cont_len_hdr": {
"fp": "22",
"name": "Content-Length",
"value": ">1",
"cmt": "el encabezado content-length/transfer-encoding:chunked está presente con cualquiera de los valores de tamaño: [0,1,>1]"
},
"cnx": {
"ka": false,
"c": true
}
},
"p6f": {
"type": "get_accept_encoding_full",
"fp": "02",
"cont_enc_hdr": {
"value": "br",
"empty_value": false,
"total_plus": 0
}
},
"p6l": {
"type": "get_accept_encoding_less",
"fp": "02",
"cont_enc_hdr": {
"value": "br",
"empty_value": false,
"total_plus": 0
}
},
"p7a": {
"type": "options_allow_hdr",
"fp": "14254c5e72000000",
"status_line": {
"http_version": {
"fp": "14",
"val_cmt": "HTTP/1.1"
},
"status_code": {
"fp": "25",
"val_cmt": "405"
},
"http_reason": {
"fp": "4c5e",
"val_cmt": "Method Not Allowed"
},
"sl_reversed_db": {
"http_version": "HTTP/1.1",
"status_code": [
405,
403,
204,
418,
404
],
"http_reason": "Method Not Allowed"
}
},
"cont_len_hdr": {
"fp": "72",
"name": "Transfer-Encoding",
"value": ">1",
"cmt": "el encabezado content-length/transfer-encoding:chunked está presente con cualquiera de los valores de tamaño: [0,1,>1]"
},
"allow_hdr": {
"fp": "000000",
"cmt": "este encabezado no se utiliza"
},
"cnx": {
"ka": true,
"c": false
}
}
}
Observe que la matriz "status_code" contiene múltiples códigos de estado HTTP. Esto ocurre porque diferentes servidores pueden usar la misma frase de razón para diferentes códigos de estado, lo que resulta en hashes FNV-1a idénticos.
La opción comparadora "-C/--compare" compara dos huellas digitales verbosus e imprime las diferencias entre los componentes principales de cada una de las sondas.
Por ejemplo, comparar las siguientes dos huellas digitales para Google y YouTube:
HTTPBasma.exe --compare 01140a85e4001320958a22142494d62214254c5e2214254c5e22080014254c5e220000000000,01140a85e4011320958a22142494d67214254c5e2214254c5e22080014254c5e220000000000
Da como resultado esta salida:
< FPrnt-1 Vs. FPrnt-2 >
[ P1 ]
{Strict-Transport-Security}
encabezado sts: 00 != 01
[ P2 ]
[ P3 ]
{Content-Length}
cl_name: 2 != 7
[ P4 ]
[ P5 ]
[ P6F ]
[ P6L ]
[ P7a ]
La salida revela diferencias específicamente en el componente hash de la sonda P1, donde el encabezado STS está presente en la primera fp y no en la otra. Además, la codificación de "Content-Length" es diferente entre las dos huellas digitales para la sonda P3.
Netomize proporciona versiones compiladas para Windows y Linux x64 del código público en este repositorio. Además, el archivo CSV de huellas digitales HTTP-Basma de 1 millón de sitios Majestic - conjunto de datos se incluye en el primer lanzamiento.
Abierto a pull requests e issues. Los comentarios y sugerencias son muy apreciados.