
Nel campo della cybersicurezza, identificare e caratterizzare con precisione i server web è fondamentale per il rilevamento delle minacce, la valutazione delle vulnerabilità e la mappatura della rete. Presentiamo HTTP-Basma, un nuovo algoritmo di fingerprinting attivo che svela profili unici dei server attraverso un approccio multilivello.
HTTP-Basma è disponibile all'indirizzo https://httpbasma.netomize.ca/
Nell'ambito della cybersecurity, identificare e caratterizzare con precisione i web server è fondamentale per il rilevamento delle minacce, la valutazione delle vulnerabilità e la mappatura della rete. Presentiamo HTTP-Basma, un nuovo algoritmo di fingerprinting attivo che svela profili server unici attraverso un approccio multi-livello, affrontando così questa sfida.
Caratteristiche principali: Richieste su misura, risposte rivelatrici: HTTP-Basma invia 8 sonde HTTP meticolosamente progettate, ottenendo risposte distintive che riflettono le configurazioni del server. Doppio hashing per la versatilità. L'algoritmo genera due hash:
Clustering e caccia: questi hash abilitano il clustering dei server, l'identificazione di server unici e simili e l'individuazione di attori malintenzionati con maggiore sicurezza.
Design modulare per l'espansione: l'architettura dell'algoritmo favorisce l'aggiunta di nuove varianti di hashing, incoraggiando collaborazione e adattabilità.
In questo documento, esaminiamo innanzitutto i notevoli lavori esistenti sul fingerprinting HTTP e poi esploriamo funzionalità, design, architettura e risultati dell'algoritmo. Inoltre, presenteremo risultati significativi emersi dalla scansione dei primi 1 milione di siti web Majestic, inclusa l'identificazione e il clustering dei server HTTP C&C per varie famiglie di malware.
L'idea centrale dell'algoritmo di HTTP-Basma si basa sull'invio di 8 richieste HTTP appositamente costruite con requisiti diversi per ottenere risposte differenti dal server. Una volta ricevuta la risposta del server, la riga di stato HTTP viene analizzata chirurgicamente in tutti i suoi elementi e codificata in modo ottimale. Inoltre, anche alcuni header della risposta del server vengono verificati per la codifica.
Le richieste che invia sono dei seguenti tipi:
Dopo ogni richiesta, la risposta del server viene analizzata per estrarre header specifici e i loro valori. Questi dati estratti vengono ulteriormente elaborati, inclusi dissezione e codifica, per generare un fingerprint reversibile.
I dettagli tecnici completi sul funzionamento dell'algoritmo sono contenuti nel documento allegato.
Questa filosofia di design modulare considera il fingerprint di ogni richiesta come un blocco fondamentale, consentendo un refactoring elegante, con la possibilità di aggiungere e sottrarre il fingerprint di qualsiasi richiesta.
Esempi di fingerprint:
- verbosus fp: 011420958a0014514bd5221420958a221420958a221420958a2200001420958a22000000001f
- pacto fp: 02464ae8b7d86f82c9918e2c2b9d6b91
- note: false-positive rate (72/986,910)
- verbosus fp: 01142494d60914514bd522142494d6221420958a701420958a220000140e04922032c37f1609
- pacto fp: 020769322f3d94ac2f258ddf5ce08502
- note-1: false-positive rate 0
- note-2: tevedadav.site/43.209.165.126:443 (TLS)
- sample-(sha-256): 9aa1dec8dd12f8adc7fc1274e1958f3613450109ee8b4ec6442a0fcf06df0972
- verbosus fp: 01140a85e40014512f3612140a85e422140a85e422140a85e4220000140a85e4220000000001
- pacto fp: 0207292309a7a7e798e417d69df5f2a5
- note: false-positive rate (73/986,910)
- verbosus fp: 01140a85e4001320958a22142494d62214254c5e2214254c5e22080014254c5e220000000000
- pacto fp: 0202be780e1eaae0eaa6184e20c909b6
- note: false-positive rate (4/986,910)
- verbosus fp: 01140a85e4011320958a22142494d67214254c5e2214254c5e22080014254c5e220000000000
- pacto fp: 02cc5be6d05192e17de041538508bc22
- note: false-positive rate (38/986,910)
- verbosus fp: 01140a85e40914514bd522140a85e4721420958a701420958a220800140a85e4720000001609
- pacto fp: 0221b4e46bbd0e5c037f5a852ca3fdc0
- note: false-positive rate (6/986,910)
HTTP-Basma è uno strumento C++ che ho sviluppato per dimostrare la praticità e la validità di questo algoritmo. Utilizza la libreria di Chilkat per tutte le interazioni socket HTTP e si avvale di altre classi di supporto all'interno della libreria. Inoltre, lo strumento include una funzione demangler in grado di analizzare e invertire il fuzzy-hash verbosus, producendo un oggetto JSON completo, e una funzione di confronto che restituisce le differenze tra due fingerprint verbosus.
Tieni presente che alcuni output dello strumento potrebbero usare numeri di sonda leggermente diversi, ma l'ordine sottostante rimane coerente: P1->P1, P2->P2, P3->P3, P4->P4, P->P5, P6->P6F, P7->P6L, P8->P7a.
Usage:
HTTP-Basma [OPTION...]
-d, --domain arg domains/IPs (you may query multiple domains, comma separated)
-p, --port arg port number
-s, --ssl does the HTTP connection have to be carried over SSL/TLS?
-q, --qpath check domain with url path included (not recommended)
-w, --redirect enable/disable HTTP redirects. If disabled/false, only the next redirect is followed,
otherwise, all redirects are followed (default: true)
-t, --ctimeout arg socket connection timeout value in seconds (default: 1)
-g, --rtimeout arg socket read (from the server) timeout value in seconds (default: 1)
-e, --sleep arg the duration (in milliseconds) to pause between each request (default: 100)
-x, --proxy arg proxy config: <"socks4|socks5|http">,<domain>,<port>,<bool:direct_tls>,<login>,<pass>
all values are comma-separated. <direct_tls> is ignored with a non-HTTP proxy
-f, --file arg file with list of domains/IPs (requires "-c/--csv" or "-j/--json")
-P, --parallel Scan list of domains passed via the "-f/--file" option in parallel
-c, --csv save to csv file; if the option 'n' is not specified, the CSV filename will be auto
generated
-n, --csvfile arg name of the CSV file
-j, --json save to json file; if the option 'l' is not specified, the JSON filename will be auto
generated
-l, --jsonfile arg name of the JSON file
-r, --saveh save request response headers
-o, --pjson display fingerprint dissection to the console as a JSON object
-i, --demangle_json arg demangle a fingerprint into a detailed json format (you can have more than one, comma
separated)
-u, --demangle_txt arg output a concise text format of the fingerprint, comma-separated for multiple results
-C, --compare arg compare two verbosus fingerprints (comma-separated)
-a, --pacto arg obtain the Pacto fingerprint using Verbosus
-h, --help print usage
Quando si interroga un determinato dominio/IP, la risposta può essere salvata in un file CSV o JSON con una grande quantità di informazioni sugli header della risposta del server e sul fingerprint unico di ogni sonda.
Ad esempio, per ottenere il fingerprint del server https://google.com e salvare i risultati in un file JSON e CSV, salvando anche gli header della risposta HTTP di ogni sonda:
HTTPBasma.exe -d https://google.com --json --csv --saveh
Nella cartella Output troverai il file CSV google_hb_results_2026-05-19_08-35-38_am.csv e il file JSON google_hb_results_2026-05-19_08-35-38_am.json.
La funzione demangler dello strumento "-i/--demangle_json" prende un fingerprint verbosus e ricostruisce gli attributi di ogni sonda, producendo un oggetto JSON completo. In particolare, quando tenta di invertire gli hash FNV-1a, il demangler utilizza due database locali: options.csv per i metodi HTTP consentiti e status_line_db.csv per le frasi di motivo della riga di stato. Se uno di questi file di database manca, la relativa funzionalità di inversione degli hash viene automaticamente disabilitata. Questi database sono stati compilati da una scansione dei primi 1 milione di siti web Majestic.
La demangling del fingerprint verbosus per il 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": "this header is not used"
}
},
"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": "content-length/transfer-encoding:chunked header is present with either of the size values: [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": "content-length/transfer-encoding:chunked header is present with either of the size values: [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": "content-length/transfer-encoding:chunked header is present with either of the size values: [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": "content-length/transfer-encoding:chunked header is present with either of the size values: [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": "content-length/transfer-encoding:chunked header is present with either of the size values: [0,1,>1]"
},
"allow_hdr": {
"fp": "000000",
"cmt": "this header is not used"
},
"cnx": {
"ka": true,
"c": false
}
}
}
Osserva che l'array "status_code" contiene più codici di stato HTTP. Ciò accade perché server diversi potrebbero usare la stessa frase di motivo per codici di stato differenti, producendo hash FNV-1a identici.
L'opzione del comparatore "-C/--compare" confronta due fingerprint verbosus e stampa le differenze tra i componenti principali di ciascuna sonda.
Ad esempio, confrontando i seguenti due fingerprint per Google e YouTube:
HTTPBasma.exe --compare 01140a85e4001320958a22142494d62214254c5e2214254c5e22080014254c5e220000000000,01140a85e4011320958a22142494d67214254c5e2214254c5e22080014254c5e220000000000
Il risultato è il seguente output:
< FPrnt-1 Vs. FPrnt-2 >
[ P1 ]
{Strict-Transport-Security}
sts header: 00 != 01
[ P2 ]
[ P3 ]
{Content-Length}
cl_name: 2 != 7
[ P4 ]
[ P5 ]
[ P6F ]
[ P6L ]
[ P7a ]
L'output rivela differenze specificamente nella componente hash della sonda P1, dove l'header STS è presente nel primo fp ma non nell'altro. Inoltre, la codifica di "Content-Length" è diversa tra i due fingerprint per la sonda P3.
Netomize fornisce versioni compilate per Windows e Linux x64 del codice pubblico presente in questo repository. Inoltre, il file CSV dei fingerprint HTTP-Basma del 1 milione di siti Majestic - data set è incluso nel primo rilascio.
Aperto a pull request e issue. Commenti e suggerimenti sono molto apprezzati.