
Mustererkennung für Hosts, Dienste und Inhalte
Recog ist ein Framework zur Identifizierung von Produkten, Diensten, Betriebssystemen und Hardware, indem Fingerprints mit Daten abgeglichen werden, die von verschiedenen Netzwerk-Sonden zurückgegeben werden. Mit Recog lassen sich auf einfache Weise nützliche Informationen aus Webserver-Bannern, SNMP-Systembeschreibungsfeldern und vielem mehr extrahieren.
Recog ist Open Source. Weitere Informationen finden Sie in der Datei LICENSE.
Am 31. März 2022 wurden die Recog-Inhalte - XML-Fingerprint-Dateien und Dienstprogramme - von der Bibliotheksimplementierung des Recog-Frameworks getrennt. Das ursprüngliche Recog-Repository enthält nun die Recog-Inhalte, und das Recog-Ruby-Repository enthält die Ruby-Sprachimplementierung. Die Recog-Inhalte sind als Git-Submodul in Recog-Ruby enthalten und im Verzeichnis recog verschachtelt. Alle Recog-Gem-Versionen ab 3.0.0 nach der Trennung werden: 1. das XML-Fingerprint-Verzeichnis unter dem Verzeichnis recog enthalten und 2. nur das Werkzeug recog_match enthalten, da sich die anderen Werkzeuge auf die Fingerprint-Verwaltung konzentrieren.
Zusammen mit der Aufteilung des Repositorys wurde der Standard-Branch von master in main umbenannt. Alle Klone, die vor diesen Änderungen erstellt wurden, müssen in Ihrer lokalen Umgebung manuell aktualisiert werden. Wenn Sie einen Fork haben, navigieren Sie zu den Einstellungen Ihres Forks und folgen Sie den Anweisungen unter Umbenennen eines Branches, um den Standard-Branch in main zu ändern.
git branch -m master main
git fetch origin
git branch -u origin/main main
git remote set-head origin -a
Optional können Sie den folgenden Befehl ausführen, um Tracking-Verweise auf den alten Branch-Namen zu entfernen.
# dry-run to confirm stale references that will be deleted before proceeding
git remote prune origin --dry-run
git remote prune origin
Falls Sie zuvor den Upstream-Tracking-Branch upstream-master verwendet haben, führen Sie die folgenden Befehle aus, um den alten Branch zu entfernen und einen neuen Upstream-Tracking-Branch zu erstellen.
git branch -d upstream-master
git checkout -b upstream-main --track upstream/main
Optional können Sie den folgenden Befehl ausführen, um die Tracking-Verweise auf den alten Upstream-Branch-Namen zu entfernen.
# dry-run to confirm stale references that will be deleted before proceeding
git remote prune upstream --dry-run
git remote prune upstream
Recog besteht sowohl aus XML-Fingerprint-Dateien als auch aus einer Reihe von Code, hauptsächlich in Ruby, der die Entwicklung, das Testen und die Verwendung der enthaltenen Fingerprints erleichtert. Um den enthaltenen Ruby-Code verwenden zu können, werden eine aktuelle Version von Ruby (2.31+) sowie Rubygems und das Gem bundler benötigt. Sobald diese Abhängigkeiten vorhanden sind, verwenden Sie die folgenden Befehle, um den neuesten Quellcode zu laden und alle zusätzlichen Abhängigkeiten zu installieren.
$ git clone [email protected]:rapid7/recog.git
$ cd recog
$ bundle install
Bitte beachten Sie, dass die XML-Fingerprints selbst zwar recht stabil und gut getestet sind, die Ruby-Codebasis jedoch noch relativ neu ist und sich schnell ändern kann. Kontaktieren Sie uns bitte (research[at]rapid7.com), bevor Sie den Recog-Code in Produktionsprojekten einsetzen.
Die Fingerprints in Recog werden in XML-Dateien gespeichert, die jeweils dazu dienen, eine bestimmte Protokoll-Antwortzeichenkette oder ein bestimmtes Feld abzugleichen. Beispielsweise kann die Datei ssh_banners.xml das Betriebssystem, den Hersteller und manchmal auch das Hardware-Produkt ermitteln, indem sie die anfängliche Bannerzeichenkette des SSH-Daemons abgleicht.
Eine Fingerprint-Datei besteht aus einem XML-Dokument wie dem folgenden:
<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>
Die erste Zeile sollte immer aus der XML-Versionsdeklaration bestehen. Das erste Element sollte immer ein fingerprints-Block mit einem matches-Attribut sein, das angibt, welche Daten diese Fingerprint-Datei abgleichen soll. Das matches-Attribut hat normalerweise die Form protocol.field.
Innerhalb des fingerprints-Elements sollte es ein oder mehrere fingerprint-Elemente geben. Jedes fingerprint-Element muss ein pattern-Attribut enthalten, das den regulären Ausdruck enthält, der für den Abgleich der Daten verwendet werden soll. Ein optionales flags-Attribut kann angegeben werden, um zu steuern, wie der reguläre Ausdruck interpretiert werden soll. Weitere Informationen finden Sie in der Recog-Dokumentation zu FLAG_MAP.
Innerhalb des Fingerprints sollte ein description-Element eine menschenlesbare Zeichenkette enthalten, die diesen Fingerprint beschreibt.
Mindestens ein example-Element sollte vorhanden sein, jedoch sind mehrere example-Elemente bevorzugt. Diese Elemente werden als Teil der in rspec vorhandenen Testabdeckung verwendet, die validiert, dass die bereitgestellten Daten mit dem angegebenen regulären Ausdruck übereinstimmen. Wenn der Fingerprint die param-Elemente verwendet, um Feldwerte aus den Daten zu extrahieren (wie im Folgenden beschrieben), können Sie diese erwarteten Extraktionen außerdem als Attribute der example-Elemente hinzufügen. Im obigen Beispiel stellt dies:
<example service.version="4.62">RomSShell_4.62</example>
testet, dass RomSShell_4.62 mit dem angegebenen regulären Ausdruck übereinstimmt und dass der Wert von service.version 4.62 beträgt.
Die example-Zeichenkette kann base64-kodiert sein, um die Verwendung nicht druckbarer Zeichen zu ermöglichen. Um dies Recog mitzuteilen, wird dem example-Element ein _encoding-Attribut mit dem Wert base64 hinzugefügt. Base64-kodierter Text, der länger als 80 Zeichen ist, kann wie unten gezeigt mit Zeilenumbrüchen umbrochen werden, um die Lesbarkeit zu verbessern.
<example _encoding="base64">
dGllczGEAAAAlQQWMS4yLjg0MC4xMTM1NTYuMS40LjgwMAQuZGF0YS5yZW1vdmVkLjCEAAAAK
AQdZG9tYWluQ29udHJvbGxlckZ1bmN0aW9uYWxpdHkxhAAAAAMEATc=
</example>
Darüber hinaus können Beispiele in einem Verzeichnis mit demselben Basisnamen wie die XML-Datei im selben Verzeichnis wie die XML-Datei abgelegt werden:
xml/services.xml
xml/services/file1
xml/services/file2
...
Sie können dann über das _filename-Attribut geladen werden:
<example _filename="file1"/>
Dies ist für lange Beispiele nützlich.
Die param-Elemente enthalten ein pos-Attribut, das angibt, welches Erfassungsfeld aus dem pattern extrahiert werden soll, oder 0 für eine statische Zeichenkette. Das name-Attribut ist der Schlüssel, der bei einer erfolgreichen Übereinstimmung gemeldet wird. Der value ist entweder eine statische Zeichenkette für pos-Werte von 0 oder fehlt und wird aus dem erfassten Feld übernommen.
Das value-Attribut unterstützt die Interpolation von Daten aus anderen Feldern. Dies ist oft nützlich, wenn der Wert für hw.product per Regex erfasst und dieser Wert in os.product wiederverwendet wird.
Hier ist ein Beispiel aushttp_servers.xml, in dem hw.product erfasst und wiederverwendet wird.
<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>
Es gibt eine spezielle Behandlung für temporäre Attribute, deren Name mit _tmp. beginnt. Diese Attribute können für die Interpolation verwendet werden, werden aber nicht in der Ausgabe ausgegeben. Dies ist nützlich, wenn ein bestimmter Produktname in verschiedenen Bannern, im Herstellermarketing oder bei NIST-Werten inkonsistent ist, wenn versucht wird, CPEs zu erzeugen. In diesen Fällen können die nützlichen Teile des Banners extrahiert und ein neuer Wert erzeugt werden, ohne die von einer Übereinstimmung ausgegebenen Daten zu überladen.
<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>
Diese temporären Attribute werden nicht in identifiers/fields.txt nachverfolgt.
Die folgenden Beispiele verwenden bin/recog_match, ein einfaches Ruby-Kommandozeilenwerkzeug, das die Fingerprint-Daten von Recog nutzt. Vor der Ausführung von Recog ist in der Regel eine Vorverarbeitung erforderlich, d. h. das Extrahieren von HTTP-Header-Werten usw. Alle Fingerprint-Daten finden Sie in xml/*.xml.
Identifizieren Sie FTP-Server per Fingerprint anhand der Bannerantwort des Servers nach dem Verbindungsaufbau:
# 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"}
Identifizieren Sie einen HTTP-Server per Fingerprint anhand des Werts des HTTP-Headers Set-Cookie:
# 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"}
Identifizieren Sie einen HTTP-Server per Fingerprint anhand des Werts des HTTP-Headers Server:
# 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)"}
Identifizieren Sie einen laufenden Dienst anhand der md5sum eines Favicons:
# 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"}
Identifizieren Sie einen HTTP-Server per Fingerprint anhand des Werts des HTTP-Headers WWW-Authenticate:
# 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\""}
Identifizieren Sie TLS-Server per Fingerprint anhand der Antwort des Servers auf 10 TLS-Client-Hello-Pakete. Fingerprint basierend auf 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"}
Die Benutzer und Maintainer von Recog würden sich sehr über Beiträge freuen, die Sie zum Projekt leisten können. Richtlinien und Anweisungen finden Sie in CONTRIBUTING.MD
| Funktion ✨ | rapid7/recog-ruby | rapid7/recog-java | runZeroInc/recog-go |
|---|
| CLI-Tool zur Fingerprint-Überprüfung | ✅ | ✅ | ✅ |
| CLI-Tool für Fingerprint-Abgleich | ✅ | ✅ | |
| Unterstützt base64-kodierte Beispiele | ✅ | ✅ | ✅ |
| Unterstützt dateisystembasierte externe Beispiele | ✅ | ✅ | ✅ |
| CPE-Parameterinterpolation beim Fingerprint-Abgleich | ✅ | ✅ | ✅ |