
호스트, 서비스 및 콘텐츠에 대한 패턴 인식
Recog는 다양한 네트워크 프로브가 반환한 데이터에 지문을 매칭하여 제품, 서비스, 운영 체제 및 하드웨어를 식별하는 프레임워크입니다. Recog를 사용하면 웹 서버 배너, SNMP 시스템 설명 필드 등에서 유용한 정보를 간단하게 추출할 수 있습니다.
Recog는 오픈 소스입니다. 자세한 내용은 LICENSE 파일을 참조하십시오.
2022년 3월 31일, Recog 콘텐츠(XML 지문 파일 및 유틸리티)가 Recog 프레임워크 라이브러리 구현에서 분리되었습니다. 원래 Recog 저장소에는 이제 Recog 콘텐츠가 포함되어 있으며, Recog-Ruby 저장소에는 Ruby 언어 구현이 포함되어 있습니다. Recog 콘텐츠는 git 서브모듈로 Recog-Ruby에 포함되며 recog 디렉터리 아래에 중첩되어 있습니다. 분리 이후의 Recog gem 버전 3.0.0 이상은: 1. recog 디렉터리 아래에 XML 지문 디렉터리를 포함하고, 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
선택적으로, 다음 명령을 실행하여 이전 브랜치 이름에 대한 추적 참조를 제거할 수 있습니다.
# dry-run to confirm stale references that will be deleted before proceeding
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
선택적으로, 다음 명령을 실행하여 이전 업스트림 브랜치 이름에 대한 추적 참조를 제거할 수 있습니다.
# dry-run to confirm stale references that will be deleted before proceeding
git remote prune upstream --dry-run
git remote prune upstream
Recog는 XML 지문 파일과, 주로 Ruby로 작성된, 포함된 지문을 쉽게 개발·테스트·사용할 수 있게 해주는 다양한 코드로 구성됩니다. 포함된 Ruby 코드를 사용하려면 최신 버전의 Ruby(2.31+)와 Rubygems 및 bundler gem이 필요합니다. 이러한 종속성이 준비되면 다음 명령을 사용하여 최신 소스 코드를 가져오고 추가 종속성을 설치하십시오.
$ git clone [email protected]:rapid7/recog.git
$ cd recog
$ bundle install
XML 지문 자체는 상당히 안정적이고 잘 테스트되어 있지만, Ruby 코드베이스는 아직 상당히 새롭고 빠르게 변경될 수 있다는 점에 유의하십시오. 프로덕션 프로젝트에서 Recog 코드를 사용하기 전에 저희에게 연락해 주십시오 (research[at]rapid7.com).
Recog 내의 지문은 XML 파일에 저장되며, 각 파일은 특정 프로토콜 응답 문자열 또는 필드를 매칭하도록 설계되었습니다. 예를 들어, ssh_banners.xml 파일은 초기 SSH 데몬 배너 문자열을 매칭하여 OS, 공급업체, 때로는 하드웨어 제품을 알아낼 수 있습니다.
지문 파일은 다음과 같은 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 버전 선언으로 구성되어야 합니다. 첫 번째 요소는 항상 matches 속성이 있는 fingerprints 블록이어야 하며, 이 속성은 이 지문 파일이 매칭해야 할 데이터를 나타냅니다. matches 속성은 일반적으로 protocol.field 형식입니다.
fingerprints 요소 안에는 하나 이상의 fingerprint 요소가 있어야 합니다. 모든 fingerprint는 데이터를 매칭하는 데 사용할 정규 표현식이 포함된 pattern 속성을 반드시 포함해야 합니다. 정규 표현식을 해석하는 방법을 제어하기 위해 선택적으로 flags 속성을 지정할 수 있습니다. 자세한 내용은 FLAG_MAP에 대한 Recog 문서를 참조하십시오.
지문 내부에서 description 요소는 이 지문을 설명하는 사람이 읽을 수 있는 문자열을 포함해야 합니다.
최소한 하나의 example 요소가 있어야 하지만, 여러 개의 example 요소가 권장됩니다. 이 요소들은 제공된 데이터가 지정된 정규 표현식과 일치하는지 검증하는 rspec 테스트 커버리지의 일부로 사용됩니다. 또한, 지문이 데이터에서 필드 값을 추출하기 위해 param 요소를 사용하는 경우(다음에 설명), 이 예상 추출 결과를 example 요소의 속성으로 추가할 수 있습니다. 위 예제에서 다음은:
<example service.version="4.62">RomSShell_4.62</example>
RomSShell_4.62가 제공된 정규 표현식과 일치하는지, 그리고 service.version의 값이 4.62인지 테스트합니다.
example 문자열은 인쇄할 수 없는 문자를 허용하기 위해 base64로 인코딩할 수 있습니다. 이를 Recog에 알리기 위해 example 요소에 base64 값을 가진 _encoding 속성이 추가됩니다. 80자보다 긴 base64 인코딩 텍스트는 가독성을 돕기 위해 아래와 같이 줄바꿈으로 감쌀 수 있습니다.
<example _encoding="base64">
dGllczGEAAAAlQQWMS4yLjg0MC4xMTM1NTYuMS40LjgwMAQuZGF0YS5yZW1vdmVkLjCEAAAAK
AQdZG9tYWluQ29udHJvbGxlckZ1bmN0aW9uYWxpdHkxhAAAAAMEATc=
</example>
또한, 예제는 XML 파일과 동일한 디렉터리 안에 XML 파일과 같은 기본 이름을 가진 디렉터리에 배치할 수 있습니다:
xml/services.xml
xml/services/file1
xml/services/file2
...
그런 다음 _filename 속성을 사용하여 로드할 수 있습니다:
<example _filename="file1"/>
이는 긴 예제에 유용합니다.
param 요소에는 pattern에서 추출할 캡처 필드를 나타내는 pos 속성이 포함되며, 정적 문자열의 경우 0을 사용합니다. name 속성은 매칭에 성공할 때 보고되는 키이며, value는 pos 값이 0인 경우 정적 문자열이 되거나, 값이 없으면 캡처된 필드에서 가져옵니다.
value 속성은 다른 필드의 데이터 보간을 지원합니다. 이는 정규 표현식을 통해 hw.product 값을 캡처하고 이 값을 os.product에서 재사용할 때 유용합니다.
다음은 hw.product가 캡처되어 재사용되는 http_servers.xml의 예입니다.
<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.로 시작하는 임시 속성에는 특별한 처리가 적용됩니다. 이러한 속성은 보간에는 사용할 수 있지만 출력에는 포함되지 않습니다. 이는 특정 제품 이름이 여러 배너, 공급업체 마케팅 자료, 또는 CPE 생성 시 NIST 값과 일치하지 않을 때 유용합니다. 이러한 경우 배너의 유용한 부분을 추출하여 매칭 결과로 출력되는 데이터를 복잡하게 만들지 않으면서 새 값을 만들 수 있습니다.
<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에서 추적되지 않습니다.
다음 예제들은 Recog의 지문 데이터를 사용하는 간단한 Ruby 명령줄 도구인 bin/recog_match를 사용합니다. Recog를 실행하기 전에 일반적으로 전처리가 필요합니다(예: HTTP 헤더 값 추출 등). 모든 지문 데이터는 xml/*.xml에서 찾을 수 있습니다.
연결 후 서버의 배너 응답을 기반으로 FTP 서버를 지문 식별합니다:
# 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"}
HTTP Set-Cookie 헤더 값을 사용하여 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"}
HTTP 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)"}
파비콘의 md5sum을 사용하여 실행 중인 서비스를 식별합니다:
# 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"}
HTTP WWW-Authenticate 헤더 값을 사용하여 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\""}
10개의 TLS Client Hello 패킷에 대한 서버의 응답을 기반으로 TLS 서버를 지문 식별합니다. 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"}
Recog의 사용자와 유지관리자는 프로젝트에 대한 어떤 기여도 크게 환영합니다. 지침과 안내는 CONTRIBUTING.MD를 참조하십시오.
| 기능 ✨ | rapid7/recog-ruby | rapid7/recog-java | runZeroInc/recog-go |
|---|
| 지문 검증 CLI 도구 | ✅ | ✅ | ✅ |
| 지문 매칭 CLI 도구 | ✅ | ✅ | |
| base64 인코딩 예제 지원 | ✅ | ✅ | ✅ |
| 파일 시스템 기반 외부 예제 지원 | ✅ | ✅ | ✅ |
| 지문 매칭 CPE 매개변수 보간 | ✅ | ✅ | ✅ |