
Pattern recognition for hosts, services, and content
Recog — это фреймворк для идентификации продуктов, сервисов, операционных систем и оборудования путём сопоставления отпечатков (fingerprint) с данными, полученными от различных сетевых зондов. Recog упрощает извлечение полезной информации из баннеров веб-серверов, полей описания системы SNMP и многого другого.
Recog является открытым программным обеспечением; дополнительную информацию см. в файле LICENSE.
31 марта 2022 года содержимое Recog — XML-файлы отпечатков и утилиты — было отделено от реализации библиотеки фреймворка Recog. Исходный репозиторий Recog теперь содержит содержимое Recog, а репозиторий Recog-Ruby содержит реализацию на языке Ruby. Содержимое Recog включено в Recog-Ruby как git-подмодуль и находится в каталоге recog. Все версии гема Recog после разделения, равные или больше 3.0.0, будут: 1) содержать каталог XML-отпечатков внутри каталога recog и 2) включать только инструмент recog_match, поскольку остальные инструменты ориентированы на управление отпечатками.
Вместе с разделением репозитория ветка по умолчанию была переименована с master на main. Все клоны, созданные до этих изменений, должны быть вручную обновлены в локальной среде. Если у вас есть форк, перейдите в его настройки и следуйте инструкциям по переименованию ветки, чтобы изменить ветку по умолчанию на main.
git branch -m master main
git fetch origin
git branch -u origin/main main
git remote set-head origin -a
При желании выполните следующую команду, чтобы удалить отслеживающие ссылки на старое имя ветки.
# сухой прогон для подтверждения устаревших ссылок, которые будут удалены перед выполнением
git remote prune origin --dry-run
git remote prune origin
Если вы ранее использовали вышестоящую отслеживающую ветку upstream-master, выполните следующие команды, чтобы удалить старую ветку и создать новую вышестоящую отслеживающую ветку.
git branch -d upstream-master
git checkout -b upstream-main --track upstream/main
При желании выполните следующую команду, чтобы удалить отслеживающие ссылки на старое имя вышестоящей ветки.
# сухой прогон для подтверждения устаревших ссылок, которые будут удалены перед выполнением
git remote prune upstream --dry-run
git remote prune upstream
Recog состоит как из XML-файлов отпечатков, так и из набора кода, в основном на Ruby, который упрощает разработку, тестирование и использование содержащихся отпечатков. Для использования включённого Ruby-кода требуется свежая версия Ruby (2.31+), а также Rubygems и гем bundler. После установки этих зависимостей используйте следующие команды, чтобы получить последнюю версию исходного кода и установить все дополнительные зависимости.
$ git clone [email protected]:rapid7/recog.git
$ cd recog
$ bundle install
Обратите внимание: хотя сами XML-отпечатки достаточно стабильны и хорошо протестированы, кодовая база Ruby всё ещё довольно нова и может быстро меняться. Пожалуйста, свяжитесь с нами (research[at]rapid7.com), прежде чем использовать код Recog в каких-либо производственных проектах.
Отпечатки в Recog хранятся в XML-файлах, каждый из которых предназначен для сопоставления с определённой строкой ответа протокола или полем. Например, файл ssh_banners.xml может определить ОС, производителя, а иногда и аппаратный продукт, сопоставляя начальную строку баннера демона SSH.
Файл отпечатков представляет собой XML-документ следующего вида:
<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>
Первая строка всегда должна содержать объявление версии XML. Первым элементом всегда должен быть блок fingerprints с атрибутом matches, указывающим, какие данные должен сопоставлять этот файл отпечатков. Атрибут matches обычно имеет вид protocol.field.
Внутри элемента fingerprints должен быть один или несколько элементов fingerprint. Каждый fingerprint должен содержать атрибут pattern, в котором хранится регулярное выражение для сопоставления с данными. Необязательный атрибут flags может указывать, как интерпретировать регулярное выражение. См. документацию Recog по FLAG_MAP для получения дополнительной информации.
Внутри отпечатка элемент description должен содержать читаемую человеком строку, описывающую этот отпечаток.
Должен присутствовать хотя бы один элемент example, однако предпочтительнее несколько. Эти элементы используются как часть тестового покрытия в rspec, которое проверяет, что предоставленные данные соответствуют указанному регулярному выражению. Кроме того, если отпечаток использует элементы param для извлечения значений полей из данных (описано далее), вы можете добавить эти ожидаемые извлечения в качестве атрибутов элементов example. В приведённом выше примере:
<example service.version="4.62">RomSShell_4.62</example>
проверяет, что RomSShell_4.62 соответствует заданному регулярному выражению, и что значение service.version равно 4.62.
Строка example может быть закодирована в base64, чтобы разрешить использование непечатаемых символов. Для указания этого Recog к элементу example добавляется атрибут _encoding со значением base64. Текст в base64 длиннее 80 символов может быть перенесён на новые строки, как показано ниже, для улучшения читаемости.
<example _encoding="base64">
dGllczGEAAAAlQQWMS4yLjg0MC4xMTM1NTYuMS40LjgwMAQuZGF0YS5yZW1vdmVkLjCEAAAAK
AQdZG9tYWluQ29udHJvbGxlckZ1bmN0aW9uYWxpdHkxhAAAAAMEATc=
</example>
Кроме того, примеры могут быть помещены в каталог с тем же базовым именем, что и XML-файл, в том же каталоге, что и XML-файл:
xml/services.xml
xml/services/file1
xml/services/file2
...
Затем их можно загрузить с помощью атрибута _filename:
<example _filename="file1"/>
Это полезно для длинных примеров.
Элементы param содержат атрибут pos, указывающий, какое захваченное поле из pattern следует извлечь, или 0 для статической строки. Атрибут name — это ключ, который будет сообщён в случае успешного совпадения, а value будет либо статической строкой для значений pos равных 0, либо отсутствовать и браться из захваченного поля.
Атрибут value поддерживает интерполяцию данных из других полей. Это часто полезно, когда значение для hw.product захватывается через регулярное выражение и затем используется в os.product.
Вот пример из http_servers.xml, где 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>
Существует специальная обработка для временных атрибутов, имя которых начинается с _tmp.. Эти атрибуты могут использоваться для интерполяции, но не включаются в вывод. Это полезно, когда конкретное имя продукта непостоянно в различных баннерах, маркетинговых материалах поставщика или значениях NIST при попытке сгенерировать CPE. В таких случаях полезные части баннера можно извлечь и сформировать новое значение, не засоряя данные, выдаваемые при совпадении.
<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>
Эти временные атрибуты не отслеживаются в identifiers/fields.txt.
В следующих примерах используется bin/recog_match — простой инструмент командной строки на Ruby, который использует данные отпечатков Recog. Обычно перед запуском Recog требуется предварительная обработка, например, извлечение значений HTTP-заголовков. Все данные отпечатков можно найти в xml/*.xml.
Определение FTP-серверов по ответу баннера сервера после подключения:
# Пример ввода в виде простого текста
echo -n '220 Microsoft FTP Service' | bin/recog_match xml/ftp_banners.xml -
# Пример команды с использованием 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 -
# Пример вывода
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"}
Использование значения HTTP-заголовка Set-Cookie для идентификации HTTP-сервера:
# Пример ввода в виде простого текста
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 -
# Пример команды cURL
curl --silent -I http://localhost:9001 | grep --color=never -i '^Set-Cookie:' | cut -d: -f2- | bin/recog_match xml/http_cookies.xml -
# Пример вывода
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"}
Использование значения HTTP-заголовка Server для идентификации HTTP-сервера:
# Пример ввода в виде простого текста
echo -n 'Apache/2.4.38 (Debian)' | bin/recog_match xml/http_servers.xml -
# Пример команды cURL
curl --silent -I http://localhost:9001 | grep --color=never -i '^Server:' | cut -d: -f2- | bin/recog_match xml/http_servers.xml -
# Пример вывода
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)"}
Использование md5-суммы favicon для идентификации работающего сервиса:
# Пример ввода в виде простого текста
echo -n fe22dd2bb09daccf58256611ac491469 | bin/recog_match xml/favicons.xml -
# Пример команды cURL
curl --silent http://localhost:8000/favicon.ico | md5sum | awk '{ print $1 }' | bin/recog_match xml/favicons.xml -
# Пример вывода
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"}
Использование значения HTTP-заголовка WWW-Authenticate для идентификации HTTP-сервера:
# Пример ввода в виде простого текста
echo -n 'Basic realm="monit"' | bin/recog_match xml/http_wwwauth.xml -
# Пример команды cURL
curl --silent -I http://localhost:9001 | grep --color=never -i '^WWW-Authenticate:' | cut -d: -f2- | bin/recog_match xml/http_wwwauth.xml -
# Пример вывода
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\""}
Идентификация TLS-серверов по ответу сервера на 10 пакетов TLS Client Hello. Отпечаток основан на https://github.com/salesforce/jarm
# Пример ввода в виде простого текста
echo -n 07d14d16d21d21d07c42d43d000000f50d155305214cf247147c43c0f1a823 | bin/recog_match xml/jarm.xml -
# Пример команды с использованием JARM от Salesforce против работающего слушателя Metasploit
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 -
# Пример вывода
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"}
Пользователи и сопровождающие Recog будут весьма признательны за любой ваш вклад в проект. Рекомендации и инструкции см. в CONTRIBUTING.MD
| Feature ✨ | rapid7/recog-ruby | rapid7/recog-java | runZeroInc/recog-go |
|---|
| Fingerprint verification CLI tool | ✅ | ✅ | ✅ |
| Fingerprint match CLI tool | ✅ | ✅ | |
| Supports base64 encoded examples | ✅ | ✅ | ✅ |
| Supports filesystem-based external examples | ✅ | ✅ | ✅ |
| Fingerprint match CPE param interpolation | ✅ | ✅ | ✅ |