
Reconocimiento de patrones para hosts, servicios y contenido
Recog es un framework para identificar productos, servicios, sistemas operativos y hardware mediante la comparación de huellas contra los datos devueltos por diversas sondas de red. Recog facilita la extracción de información útil de los banners de servidores web, los campos de descripción del sistema SNMP y mucho más.
Recog es de código abierto; consulte el archivo LICENSE para obtener más información.
El 31 de marzo de 2022, el contenido de Recog -los archivos XML de huellas y las utilidades- se separó de la implementación de la librería del framework Recog. El repositorio original Recog contiene ahora el contenido de Recog, y el repositorio Recog-Ruby contiene la implementación en Ruby. El contenido de Recog se incluye en Recog-Ruby como un submódulo de git y se encuentra anidado bajo el directorio recog. Todas las versiones de la gema Recog posteriores a la división, iguales o superiores a la 3.0.0, harán lo siguiente: 1. contendrán el directorio de huellas XML bajo el directorio recog, y 2. solo incluirán la herramienta recog_match, ya que las demás herramientas están enfocadas en la gestión de huellas.
Junto con la división del repositorio, la rama por defecto pasó a llamarse main en lugar de master. Cualquier clon creado antes de estos cambios deberá actualizarse manualmente en su entorno local. Si tiene un fork, navegue a la configuración de su fork y siga las instrucciones sobre cómo renombrar una rama para cambiar la rama por defecto a main.
git branch -m master main
git fetch origin
git branch -u origin/main main
git remote set-head origin -a
Opcionalmente, ejecute el siguiente comando para eliminar las referencias de seguimiento al nombre de la rama anterior.
# dry-run to confirm stale references that will be deleted before proceeding
git remote prune origin --dry-run
git remote prune origin
Si anteriormente utilizó la rama de seguimiento upstream upstream-master, ejecute los siguientes comandos para eliminar la rama antigua y crear una nueva rama de seguimiento upstream.
git branch -d upstream-master
git checkout -b upstream-main --track upstream/main
Opcionalmente, ejecute el siguiente comando para eliminar las referencias de seguimiento al nombre de la rama upstream anterior.
# dry-run to confirm stale references that will be deleted before proceeding
git remote prune upstream --dry-run
git remote prune upstream
Recog consta de archivos XML de huellas y de un conjunto de código, principalmente en Ruby, que facilita el desarrollo, las pruebas y el uso de las huellas contenidas. Para utilizar el código Ruby incluido, se requiere una versión reciente de Ruby (2.31+) junto con Rubygems y la gema bundler. Una vez instaladas estas dependencias, use los siguientes comandos para obtener el código fuente más reciente e instalar las dependencias adicionales.
$ git clone [email protected]:rapid7/recog.git
$ cd recog
$ bundle install
Tenga en cuenta que, aunque las huellas XML son bastante estables y están bien probadas, el código base de Ruby es todavía bastante nuevo y puede cambiar rápidamente. Comuníquese con nosotros (research[at]rapid7.com) antes de utilizar el código de Recog en cualquier proyecto de producción.
Las huellas de Recog se almacenan en archivos XML, cada uno diseñado para coincidir con una cadena o campo de respuesta de protocolo específico. Por ejemplo, el archivo ssh_banners.xml puede determinar el sistema operativo, el fabricante y, a veces, el producto de hardware mediante la coincidencia con la cadena inicial del banner del demonio SSH.
Un archivo de huellas consta de un documento XML como el siguiente:
<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 primera línea debe contener siempre la declaración de versión XML. El primer elemento debe ser siempre un bloque fingerprints con un atributo matches que indique con qué datos debe coincidir este archivo de huellas. El atributo matches normalmente tiene la forma protocol.field.
Dentro del elemento fingerprints debe haber uno o más elementos fingerprint. Cada fingerprint debe contener un atributo pattern, que contiene la expresión regular que se usará para comparar contra los datos. Se puede especificar un atributo opcional flags para controlar cómo se interpreta la expresión regular. Consulte la documentación de Recog para FLAG_MAP para obtener más información.
Dentro de la huella, un elemento description debe contener una cadena legible por humanos que describa esta huella.
Debe estar presente al menos un elemento example; sin embargo, se prefieren múltiples elementos example. Estos elementos se usan como parte de la cobertura de pruebas presente en rspec, que valida que los datos proporcionados coincidan con la expresión regular especificada. Además, si la huella utiliza los elementos param para extraer valores de campo de los datos (descritos a continuación), puede agregar estas extracciones esperadas como atributos de los elementos example. En el ejemplo anterior, esto:
<example service.version="4.62">RomSShell_4.62</example>
comprueba que RomSShell_4.62 coincide con la expresión regular proporcionada y que el valor de service.version es 4.62.
La cadena example puede estar codificada en base64 para permitir el uso de caracteres no imprimibles. Para indicarlo a Recog, se agrega un atributo _encoding con el valor base64 al elemento example. El texto codificado en base64 con más de 80 caracteres puede dividirse con saltos de línea, como se muestra a continuación, para facilitar la lectura.
<example _encoding="base64">
dGllczGEAAAAlQQWMS4yLjg0MC4xMTM1NTYuMS40LjgwMAQuZGF0YS5yZW1vdmVkLjCEAAAAK
AQdZG9tYWluQ29udHJvbGxlckZ1bmN0aW9uYWxpdHkxhAAAAAMEATc=
</example>
Adicionalmente, los ejemplos pueden colocarse en un directorio con el mismo nombre base que el archivo XML, en el mismo directorio que el archivo XML:
xml/services.xml
xml/services/file1
xml/services/file2
...
Luego pueden cargarse usando el atributo _filename:
<example _filename="file1"/>
Esto es útil para ejemplos largos.
Los elementos param contienen un atributo pos, que indica qué campo de captura de pattern debe extraerse, o 0 para una cadena estática. El atributo name es la clave que se reportará en caso de una coincidencia exitosa, y value será una cadena estática para valores de pos de 0, o estará ausente y se tomará del campo capturado.
El atributo value admite interpolación de datos de otros campos. Esto suele ser útil cuando se captura el valor de hw.product mediante una expresión regular y se reutiliza ese valor en os.product.
A continuación se muestra un ejemplo de http_servers.xml donde se captura y reutiliza hw.product.
<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>
Existe un tratamiento especial para los atributos temporales cuyo nombre comienza con _tmp.. Estos atributos se pueden usar para interpolación, pero no se emiten en la salida. Esto es útil cuando un nombre de producto en particular es inconsistente en varios banners, en el marketing del fabricante o con los valores de NIST al intentar generar CPEs. En estos casos, las partes útiles del banner se pueden extraer y crear un nuevo valor sin saturar los datos emitidos por una coincidencia.
<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>
Estos atributos temporales no se registran en identifiers/fields.txt.
Los siguientes ejemplos utilizan bin/recog_match, una sencilla herramienta de línea de comandos en Ruby que usa los datos de huellas de Recog. Generalmente se requiere un preprocesamiento antes de ejecutar Recog, es decir, extraer los valores de cabeceras HTTP, etc. Todos los datos de huellas se pueden encontrar en xml/*.xml.
Huella de servidores FTP basada en la respuesta del banner del servidor después de conectarse:
# 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"}
Uso del valor de la cabecera HTTP Set-Cookie para identificar un servidor 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"}
Uso del valor de la cabecera HTTP Server para identificar un servidor 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)"}
Uso del md5sum de un favicon para identificar un servicio en ejecución:
# 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"}
Uso del valor de la cabecera HTTP WWW-Authenticate para identificar un servidor 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\""}
Huella de servidores TLS basada en la respuesta del servidor a 10 paquetes TLS Client Hello. Huella basada en 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"}
Los usuarios y mantenedores de Recog agradecerían enormemente cualquier contribución que pueda hacer al proyecto. Para conocer las pautas e instrucciones, consulte CONTRIBUTING.MD.
| Característica ✨ | rapid7/recog-ruby | rapid7/recog-java | runZeroInc/recog-go |
|---|
| Herramienta CLI de verificación de huellas | ✅ | ✅ | ✅ |
| Herramienta CLI de coincidencia de huellas | ✅ | ✅ | |
| Admite ejemplos codificados en base64 | ✅ | ✅ | ✅ |
| Admite ejemplos externos basados en el sistema de archivos | ✅ | ✅ | ✅ |
| Interpolación de parámetros CPE en coincidencia de huellas | ✅ | ✅ | ✅ |