
Riconoscimento di pattern per host, servizi e contenuti.
Recog è un framework per l'identificazione di prodotti, servizi, sistemi operativi e hardware confrontando le impronte digitali con i dati restituiti da vari probe di rete. Recog semplifica l'estrazione di informazioni utili dai banner dei server web, dai campi di descrizione del sistema SNMP e molto altro.
Recog è open source; consultare il file LICENSE per maggiori informazioni.
Il 31 marzo 2022, il contenuto di Recog - i file XML delle impronte digitali e le utility - è stato separato dall'implementazione della libreria del framework Recog. Il repository originale Recog ora contiene il contenuto di Recog e il repository Recog-Ruby contiene l'implementazione in linguaggio Ruby. Il contenuto di Recog è incluso in Recog-Ruby come sottomodulo git ed è annidato nella directory recog. Tutte le versioni della gemma Recog successive alla separazione, uguali o superiori alla 3.0.0: 1. conterranno la directory delle impronte XML nella directory recog e 2. includeranno solo lo strumento recog_match poiché gli altri strumenti sono focalizzati sulla gestione delle impronte digitali.
Insieme alla separazione del repository, il branch predefinito è stato rinominato da master a main. Eventuali cloni creati prima di queste modifiche dovranno essere aggiornati manualmente nel proprio ambiente locale. Se disponi di un fork, vai alle impostazioni del fork e segui le istruzioni su rinominare un branch per impostare il branch predefinito su main.
git branch -m master main
git fetch origin
git branch -u origin/main main
git remote set-head origin -a
Facoltativamente, eseguire il seguente comando per rimuovere i riferimenti di tracciamento al vecchio nome del branch.
# dry-run to confirm stale references that will be deleted before proceeding
git remote prune origin --dry-run
git remote prune origin
Se in precedenza hai utilizzato il branch di tracciamento upstream upstream-master, esegui i seguenti comandi per rimuovere il vecchio branch e crearne uno nuovo di tracciamento upstream.
git branch -d upstream-master
git checkout -b upstream-main --track upstream/main
Facoltativamente, eseguire il seguente comando per rimuovere i riferimenti di tracciamento al vecchio nome del branch upstream.
# dry-run to confirm stale references that will be deleted before proceeding
git remote prune upstream --dry-run
git remote prune upstream
Recog è composto sia da file XML di impronte digitali sia da una serie di codice, per lo più in Ruby, che rende facile sviluppare, testare e utilizzare le impronte digitali in esso contenute. Per utilizzare il codice Ruby incluso, sono necessarie una versione recente di Ruby (2.31+), insieme a Rubygems e alla gemma bundler. Una volta installate queste dipendenze, utilizzare i seguenti comandi per recuperare l'ultimo codice sorgente e installare eventuali dipendenze aggiuntive.
$ git clone [email protected]:rapid7/recog.git
$ cd recog
$ bundle install
Si noti che, sebbene le impronte digitali XML siano piuttosto stabili e ben testate, il codebase Ruby è ancora abbastanza recente e soggetto a rapidi cambiamenti. Contattateci (research[at]rapid7.com) prima di utilizzare il codice di Recog in progetti di produzione.
Le impronte digitali all'interno di Recog sono memorizzate in file XML, ciascuno progettato per corrispondere a una specifica stringa o campo di risposta del protocollo. Ad esempio, il file ssh_banners.xml può determinare il sistema operativo, il vendor e talvolta il prodotto hardware confrontando la stringa del banner iniziale del demone SSH.
Un file di impronte digitali è costituito da un documento XML come il seguente:
<fingerprints matches="ssh.banner">
<fingerprint pattern="^RomSShell_([\d\.]+)$">
<description>Allegro RomSShell SSH</description>
<example service.version="4.62">RomSShell_4.62</example>
<param pos="0" name="service.vendor" value="Allegro"/>
<param pos="0" name="service.product" value="RomSShell"/>
<param pos="1" name="service.version"/>
</fingerprint>
</fingerprints>
La prima riga deve essere sempre costituita dalla dichiarazione di versione XML. Il primo elemento deve essere sempre un blocco fingerprints con un attributo matches che indica quali dati questo file di impronte digitali deve confrontare. L'attributo matches è normalmente nella forma protocol.field.
All'interno dell'elemento fingerprints devono esserci uno o più elementi fingerprint. Ogni fingerprint deve contenere un attributo pattern, che contiene l'espressione regolare da utilizzare per il confronto con i dati. È possibile specificare un attributo opzionale flags per controllare come l'espressione regolare deve essere interpretata. Consultare la documentazione di Recog per FLAG_MAP per maggiori informazioni.
All'interno del fingerprint, un elemento description deve contenere una stringa leggibile che descrive questa impronta digitale.
Dovrebbe essere presente almeno un elemento example, anche se sono preferiti più elementi example. Questi elementi vengono utilizzati come parte della copertura dei test in rspec, che verifica che i dati forniti corrispondano all'espressione regolare specificata. Inoltre, se il fingerprint utilizza gli elementi param per estrarre i valori dei campi dai dati (descritto di seguito), è possibile aggiungere queste estrazioni previste come attributi degli elementi example. Nell'esempio precedente, questo:
<example service.version="4.62">RomSShell_4.62</example>
verifica che RomSShell_4.62 corrisponda all'espressione regolare fornita e che il valore di service.version sia 4.62.
La stringa example può essere codificata in base64 per consentire l'uso di caratteri non stampabili. Per segnalarlo a Recog, all'elemento example viene aggiunto un attributo _encoding con valore base64. Il testo codificato in base64 più lungo di 80 caratteri può essere suddiviso su più righe come mostrato di seguito per facilitarne la lettura.
<example _encoding="base64">
dGllczGEAAAAlQQWMS4yLjg0MC4xMTM1NTYuMS40LjgwMAQuZGF0YS5yZW1vdmVkLjCEAAAAK
AQdZG9tYWluQ29udHJvbGxlckZ1bmN0aW9uYWxpdHkxhAAAAAMEATc=
</example>
Inoltre, gli esempi possono essere inseriti in una directory con lo stesso nome base del file XML, nella stessa directory del file XML:
xml/services.xml
xml/services/file1
xml/services/file2
...
Possono quindi essere caricati utilizzando l'attributo _filename:
<example _filename="file1"/>
Ciò è utile per esempi lunghi.
Gli elementi param contengono un attributo pos, che indica quale campo di acquisizione del pattern deve essere estratto, oppure 0 per una stringa statica. L'attributo name è la chiave che verrà riportata in caso di corrispondenza riuscita, mentre value sarà una stringa statica per valori pos pari a 0 oppure assente e ricavato dal campo acquisito.
L'attributo value supporta l'interpolazione di dati provenienti da altri campi. Ciò è spesso utile quando si acquisisce il valore per hw.product tramite regex e lo si riutilizza in os.product.
Ecco un esempio tratto dahttp_servers.xml in cui hw.product viene acquisito e riutilizzato.
<fingerprint pattern="^Eltex (TAU-\d+[A-Z]*(?:\.IP)?)$">
<description>Eltex TAU model VoIP gateway</description>
<example hw.product="TAU-72">Eltex TAU-72</example>
<example hw.product="TAU-1.IP">Eltex TAU-1.IP</example>
<param pos="0" name="os.vendor" value="Eltex"/>
<param pos="0" name="os.product" value="{hw.product} Firmware"/>
<param pos="0" name="os.device" value="VoIP Gateway"/>
<param pos="0" name="hw.vendor" value="Eltex"/>
<param pos="1" name="hw.product"/>
<param pos="0" name="hw.device" value="VoIP Gateway"/>
</fingerprint>
C'è una gestione speciale per gli attributi temporanei che hanno un nome che inizia con _tmp.. Questi attributi possono essere utilizzati per l'interpolazione ma non vengono emessi nell'output. Ciò è utile quando un determinato nome di prodotto è incoerente tra vari banner, marketing del vendor o valori NIST quando si tenta di generare CPE. In questi casi, le parti utili del banner possono essere estratte e si può creare un nuovo valore senza appesantire i dati emessi da una corrispondenza.
<fingerprint pattern="^foo baz switchThing-(\d{4})$">
<description>NetCorp NX series switches</description>
<example hw.product="NX8200">foo baz switchThing-8200</example>
<param pos="0" name="hw.vendor" value="NetCorp"/>
<param pos="0" name="hw.product" value="NX{_tmp.001}"/>
<param pos="2" name="_tmp.001"/>
</fingerprint>
Questi attributi temporanei non vengono tracciati in identifiers/fields.txt.
Gli esempi seguenti utilizzano bin/recog_match, un semplice strumento da riga di comando in Ruby che usa i dati delle impronte digitali di Recog. Generalmente è richiesta una pre-elaborazione prima di eseguire Recog, ad esempio l'estrazione dei valori degli header HTTP, ecc. Tutti i dati delle impronte digitali si trovano in xml/*.xml.
Riconoscere i server FTP in base alla risposta del banner del server dopo la connessione:
# Example plaintext input
echo -n '220 Microsoft FTP Service' | bin/recog_match xml/ftp_banners.xml -
# Example command using nmap
nmap -sV -script=banner -p 21 192.168.123.13 | grep --color=never '_banner' | cut -d: -f2- | bin/recog_match xml/ftp_banners.xml -
# Example output
MATCH: {"matched"=>"Microsoft FTP Server on Windows XP, 2003 or later without version", "service.vendor"=>"Microsoft", "service.product"=>"IIS", "service.family"=>"IIS", "service.cpe23"=>"cpe:/a:microsoft:iis:-", "os.vendor"=>"Microsoft", "os.family"=>"Windows", "os.product"=>"Windows", "os.cpe23"=>"cpe:/o:microsoft:windows:-", "host.name"=>"220", "service.protocol"=>"ftp", "fingerprint_db"=>"ftp.banner", "data"=>"220 Microsoft FTP Service"}
Utilizzo del valore dell'header HTTP Set-Cookie per riconoscere un server HTTP:
# Example plaintext input
echo 'laravel_session=eyJ...etc..etc...%3D; expires=Mon, 13-Mar-2023 16:48:58 GMT; Max-Age=7200; path=/; httponly; samesite=lax' | bin/recog_match xml/http_cookies.xml -
# Example cURL command
curl --silent -I http://localhost:9001 | grep --color=never -i '^Set-Cookie:' | cut -d: -f2- | bin/recog_match xml/http_cookies.xml -
# Example output
MATCH: {"matched"=>"Laravel PHP web application framework", "service.vendor"=>"Laravel", "service.product"=>"Laravel", "service.cpe23"=>"cpe:/a:laravel:laravel:-", "service.protocol"=>"http", "fingerprint_db"=>"http_header.cookie", "data"=>"laravel_session=eyJ...etc..etc...%3D; expires=Mon, 13-Mar-2023 16:48:58 GMT; Max-Age=7200; path=/; httponly; samesite=lax"}
Utilizzo del valore dell'header HTTP Server per riconoscere un server HTTP:
# Example plaintext input
echo -n 'Apache/2.4.38 (Debian)' | bin/recog_match xml/http_servers.xml -
# Example cURL command
curl --silent -I http://localhost:9001 | grep --color=never -i '^Server:' | cut -d: -f2- | bin/recog_match xml/http_servers.xml -
# Example output
MATCH: {"matched"=>"Apache", "service.vendor"=>"Apache", "service.product"=>"HTTPD", "service.family"=>"Apache", "service.version"=>"2.4.38", "service.cpe23"=>"cpe:/a:apache:http_server:2.4.38", "apache.info"=>"(Debian)", "service.protocol"=>"http", "fingerprint_db"=>"http_header.server", "data"=>"Apache/2.4.38 (Debian)"}
Utilizzo del valore md5sum di una favicon per identificare un servizio in esecuzione:
# Example plaintext input
echo -n fe22dd2bb09daccf58256611ac491469 | bin/recog_match xml/favicons.xml -
# Example cURL command
curl --silent http://localhost:8000/favicon.ico | md5sum | awk '{ print $1 }' | bin/recog_match xml/favicons.xml -
# Example output
MATCH: {"matched"=>"Drupal CMS", "service.vendor"=>"Drupal", "service.product"=>"CMS", "service.certainty"=>"0.5", "service.cpe23"=>"cpe:/a:drupal:drupal:-", "service.protocol"=>"", "fingerprint_db"=>"favicon.md5", "data"=>"fe22dd2bb09daccf58256611ac491469"}
Utilizzo del valore dell'header HTTP WWW-Authenticate per riconoscere un server HTTP:
# Example plaintext input
echo -n 'Basic realm="monit"' | bin/recog_match xml/http_wwwauth.xml -
# Example cURL command
curl --silent -I http://localhost:9001 | grep --color=never -i '^WWW-Authenticate:' | cut -d: -f2- | bin/recog_match xml/http_wwwauth.xml -
# Example output
MATCH: {"matched"=>"Minot", "service.vendor"=>"Tildeslash", "service.product"=>"Monit", "service.cpe23"=>"cpe:/a:tildeslash:monit:-", "service.protocol"=>"http", "fingerprint_db"=>"http_header.wwwauth", "data"=>"Basic realm=\"monit\""}
Riconoscere i server TLS in base alla risposta del server a 10 pacchetti TLS Client Hello. Impronta digitale basata su https://github.com/salesforce/jarm
# Example plaintext input
echo -n 07d14d16d21d21d07c42d43d000000f50d155305214cf247147c43c0f1a823 | bin/recog_match xml/jarm.xml -
# Example command using Salesforce's JARM against a running Metasploit listener
python3 $code/jarm/jarm.py -p 8443 192.168.123.1 | grep --color=never 'JARM: ' | awk -F: '{ print $2 }' | bin/recog_match xml/tls_jarm.xml -
# Example output
MATCH: {"matched"=>"Metasploit listener", "service.vendor"=>"Rapid7", "service.product"=>"Metasploit", "service.cpe23"=>"cpe:/a:rapid7:metasploit:-", "service.protocol"=>"tls", "fingerprint_db"=>"tls.jarm", "data"=>"07d14d16d21d21d07c42d43d000000f50d155305214cf247147c43c0f1a823"}
Gli utenti e i manutentori di Recog apprezzerebbero molto qualsiasi contributo tu possa apportare al progetto. Per linee guida e istruzioni, consultare CONTRIBUTING.MD.
| Funzionalità ✨ | rapid7/recog-ruby | rapid7/recog-java | runZeroInc/recog-go |
|---|
| Strumento CLI per la verifica delle impronte digitali | ✅ | ✅ | ✅ |
| Strumento CLI per la corrispondenza delle impronte digitali | ✅ | ✅ | |
| Supporta esempi codificati in base64 | ✅ | ✅ | ✅ |
| Supporta esempi esterni basati su filesystem | ✅ | ✅ | ✅ |
| Interpolazione dei parametri CPE nella corrispondenza delle impronte | ✅ | ✅ | ✅ |