The users and maintainers of Recog would greatly appreciate any contributions you can make to the project. These contributions typically come in the form of filed bugs/issues or pull requests (PRs). These contributions routinely result in new versions of the recog gem being released. The process for everything is described below.
If you encounter any bugs or problems with Recog, please file them here, providing as much detail as possible. If the bug is straight-forward enough and you understand the fix for the bug well enough, you may take the simpler, less-paperwork route and simply fill a PR with the fix and the necessary details.
Recog uses a model nearly identical to that of
Metasploit as outlined
here,
at least from a git
perspective. If you've been through that process
(or, even better, you've been through it many times with many people), you can
do exactly what you did for Metasploit but with Recog and ignore the rest of
this document.
On the other hand, if you haven't, read on!
Generally, this should only need to be done once, or if you need to start over.
-
Fork Recog: Visit https://github.com/rapid7/recog and click Fork, selecting your github account if prompted
-
Clone
git@github.com:<your-github-username>/recog.git
, replacing<your-github-username>
with, you guessed it, your Github username. -
Add the master Recog repository as your upstream:
git remote add upstream git://github.com/rapid7/recog.git
-
Update your
.git/config
to ensure that theremote ["upstream"]
section is configured to pull both branches and PRs from upstream. It should look something like the following, in particular the secondfetch
option:[remote "upstream"] url = git@github.com:rapid7/recog.git fetch = +refs/heads/*:refs/remotes/upstream/* fetch = +refs/pull/*/head:refs/remotes/upstream/pr/*
-
Fetch the latest revisions, including PRs:
git fetch --all
If you have a contribution to make, first create a branch to contain your work. The name is yours to choose, however generally it should roughly describe what you are doing. In this example, and from here on out, the branch will be FOO, but you should obviously change this:
git fetch --all
git checkout master
git rebase upstream/master
git checkout -b FOO
Now, make your changes, commit as necessary with useful commit messages.
Please note that changes to lib/recog/version.rb in PRs are almost never necessary.
Now push your changes to your fork:
git push origin FOO
Finally, submit the PR. Navigate to https://github.com/<your-github-username>/recog/compare/FOO
, fill in the details and submit.
When your PR is submitted, it will be automatically subjected to the full run of tests in Travis, however you are encourage to perform testing before submitting the PR. To do this, simply run rake tests
.
-
Create a single fingerprint for each product as long as the pattern remains clear and readable. If that is not possible, the pattern should be logically decomposed into additional fingerprints.
-
Create regular expressions that allow for flexible version number matching. This ensures greater probability of matching a product. For example, all known public releases of a product report either
major.minor
ormajor.minor.build
format version numbers. If the fingerprint strictly matches this version number format, it would fail to match a modified build of the product that reports only amajor
version number format.
Once a fingerprint has been added, the example
entries can be tested by executing bin/recog_verify
against the fingerprint file:
bin/recog_verify xml/ssh_banners.xml
Matches can be tested on the command-line in a similar fashion:
$ echo 'OpenSSH_6.6p1 Ubuntu-2ubuntu1' | bin/recog_match xml/ssh_banners.xml -
MATCH: {"matched"=>"OpenSSH running on Ubuntu 14.04", "service.version"=>"6.6p1", "openssh.comment"=>"Ubuntu-2ubuntu1", "service.vendor"=>"OpenBSD", "service.family"=>"OpenSSH", "service.product"=>"OpenSSH", "os.vendor"=>"Ubuntu", "os.device"=>"General", "os.family"=>"Linux", "os.product"=>"Linux", "os.version"=>"14.04", "service.protocol"=>"ssh", "fingerprint_db"=>"ssh.banner", "data"=>"OpenSSH_6.6p1 Ubuntu-2ubuntu1"}
Given the number of fingerprints in Recog, it can be common for specific products, vendors, or services to be identified with different spellings and casing.
To limit the creep of slightly-different-names, the bin/recog_standardize
script can be used to extract all identifiers and merge them into the known lists.
To get started, run the recog_standardize
tool:
ruby bin/recog_standardize
Review any new additions to the text files under identifiers/
. If any of these names are close to an existing name, update the offending fingerprint to use
the existing name instead. Once the fingerprints are fixed, removed the "extra" names from the identifiers files, and run the tool again.
There exists some automation to update the CPEs that might be asserted with some recog fingerprints. This should be run periodically to ensure that all fingerprints that could have CPEs do, etc.
First, setup a python3 venv:
python3 -m venv venv
source venv/{bin,Scripts}/activate
pip install -r requirements.txt
Download the latest CPE 2.3 dictionary:
curl -o official-cpe-dictionary_v2.3.xml.gz https://nvd.nist.gov/feeds/xml/cpe/dictionary/official-cpe-dictionary_v2.3.xml.gz && \
gunzip official-cpe-dictionary_v2.3.xml.gz
Run the CPE automation against every XML file:
# Update the CPEs (sequentially)
ls xml/*.xml | xargs -i python update_cpes.py {} official-cpe-dictionary_v2.3.xml cpe-remap.yaml 2>>errors.txt
You may want to use GNU parallel
to speed things up:
# Update the CPEs (with GNU Parallel)
ls xml/*.xml | parallel --gnu "python update_cpes.py {} official-cpe-dictionary_v2.3.xml cpe-remap.yaml" 2>>errors.txt
Clean up the whitespace across all fingerprints:
ruby bin/recog_cleanup
Any mismatched fingerprints will be listed in errors.txt
for eventual
maintenance. The cpe-remap.yaml
file can be used to map between
vendor/product/etc differences between Recog and CPE, or to work around bugs in
either.
(Note: this portion is a work-in-progress. Please update it as things change)
Much like with the process of submitting PRs, Recog's process for landing PRs is very similar to Metasploit's process for landing PRs. In short:
-
Follow the "Fork and Clone" steps from above
-
Update your
.git/config
to ensure that theremote ["upstream"]
section is configured to pull both branches and PRs from upstream. It should look something like the following, in particular the secondfetch
option:[remote "upstream"] url = git@github.com:rapid7/recog.git fetch = +refs/heads/*:refs/remotes/upstream/* fetch = +refs/pull/*/head:refs/remotes/upstream/pr/*
-
Fetch the latest revisions, including PRs:
git fetch --all
-
Checkout and branch the PR for testing. Replace
PR
below with the actual PR # in question:git checkout -b landing-PR upstream/pr/PR
-
Test the PR (see the Testing section above)
-
Merge with master, re-test, validate and push:
git checkout -b upstream-master --track upstream/master git merge -S --no-ff --edit landing-PR # merge the PR into upstream-master # re-test if/as necessary git push upstream upstream-master:master --dry-run # confirm you are pushing what you expect git push upstream upstream-master:master # push upstream-master to upstream:master
-
If applicable, release a new version (see next section)
When Recog's critical parts are modified, for example its fingerprints or underlying supporting code, a new version must eventually be released. These new releases can then be optionally included in projects such as Metasploit or products such as Rapid7's Nexpose in a controlled manner. Releases for non-functional updates such as updates to documentation are not necessary.
When a new version of Recog is to be released, you must follow the instructions below.
-
If are not already a Recog project contributor for the Recog gem (you'd be listed here under OWNERS), become one:
- Get an account on Rubygems
- Contact one of the Recog project contributors (listed here under OWNERS and have them add you to the Recog gem. They'll need to run:
gem owner recog -a EMAIL
-
Edit lib/recog/version.rb and increment
VERSION
. Commit and push to rapid7/recog master. -
Run
rake release
. Among other things, this creates the new gem, uploads it to Rubygems and tags the release with a tag likev<VERSION>
, where<VERSION>
is replaced with the version fromversion.rb
. For example, if you release version 1.2.3 of the gem, the tag will bev1.2.3
. -
If your default remote repository is not
rapid7/recog
, you must ensure that the tags created in the previous step are also pushed to the right location(s). For example, iforigin
is your fork of recog andupstream
israpid7/master
, you should rungit push --tags --dry-run upstream
to confirm what tags will be pushed and thengit push --tags upstream
to push the tags.