Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add CPEs to recog fingerprints #172

Merged
merged 55 commits into from
Aug 29, 2018
Merged

Conversation

jhart-r7
Copy link
Contributor

@jhart-r7 jhart-r7 commented Aug 24, 2018

This is a proposal for adding CPEs to recog along with code to keep these values maintained. The CPEs added are based off of service, os, and hw fingerprints in recog that have a vendor and product that map to a known valid combo in the CPE 2.3 dictionary.

When present, a version will also be included in the CPE value:

    <param pos="0" name="service.cpe23" value="cpe:/a:vmware:zimbra_desktop:1"/>

In cases where the original fingerprint would use the interpolated value for the version, this CPE functionality follows the same convention, requiring consumers to interpolate the correct version when emitting the CPE fingerprints, for example:

    <param pos="0" name="service.cpe23" value="cpe:/a:vmware:zimbra_desktop:{service.version}"/>

The CPEs are 2.3 URIs, which is backwards compatible with 2.2.

This doesn't add CPEs to everything. There are many factors that contribute to this:

  • Not every vendor or product name used in Recog is valid in the CPE 2.3 dictionary. The maintenance code does support manual remapping of vendors and products.
  • Similarly, not every vendor or product might be valid or applicable for the given fingerprint type. For example, Microsoft Exchange is a valid vendor and product for a service, but not an os.
  • ...

I don't believe this should have any impact on current consumers because this is just another param element with a new name.

There are two parts to this PR:

  • Updates to the recog XML adding CPEs where possible
  • Python code to maintain the CPE values in recog XML, including a JSON file to support remapping between Rapid7-isms and CPE. Note that the maintenance code is written in python 3 for lack of a ruby XML library that did what I needed, plus I just wanted to do this in python.

Feel free to review both, however it may be better to examine the CPEs added to the recog XML first.

For using the updating code, you'll need to fetch the CPE 2.3 XML dictionary:

curl -s  https://nvd.nist.gov/feeds/xml/cpe/dictionary/official-cpe-dictionary_v2.3.xml.gz | pigz -d > official-cpe-dictionary_v2.3.xml

Now run the update code against every XML file in recog, providing as arguments the path to the recog XML file, the path to the CPE 2.3 XML dictionary and the path to a JSON file that maps Rapid7 vendor and product names to their CPE equivalents. I expedite this with parallel and save the error output for further remapping or recog bug fixing:

ls xml/*.xml | parallel --gnu "./update_cpes.py {} official-cpe-dictionary_v2.3.xml  remap.json && xmllint --format --noblanks {} > {}.bak &&  mv {}.bak {} || echo {}" 2> errors.txt

Copy link
Contributor

@tsellers-r7 tsellers-r7 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It probably wouldn't hurt to include a link to the CPE dictionary download page ( https://nvd.nist.gov/products/cpe ) or similar reference to make finding the source files easier.

update_cpes.py Outdated
if vendor and product:
if not cpe_type in cpe_vp_map:
print(cpe_type)
logging.error("Didn't find CPE type %s", cpe_type)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding the vendor/product to this output would provide useful context.
For example:

Existing:

a
ERROR:root:Didn't find CPE type a

Possible output

using logging.error("Didn't find CPE type '%s' for '%s %s'", cpe_type, vendor, product)

a
ERROR:root:Didn't find CPE type a for Oracle XML DB

update_cpes.py Outdated

def main():
if len(sys.argv) != 4:
raise ValueError("Expecting exactly 3 arguments; recog XML file, CPE 2.3 XML dictionary, JSON remapping, got {}".format(len(sys.argv) - 1))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tossing at logging would result in cleaner output.

Traceback (most recent call last):
  File "./update_cpes.py", line 200, in <module>
    try: sys.exit(main())
  File "./update_cpes.py", line 54, in main
    raise ValueError("Expecting exactly 3 arguments; recog XML file, CPE 2.3 XML dictionary, JSON remapping, got {}".format(len(sys.argv) - 1))
ValueError: Expecting exactly 3 arguments; recog XML file, CPE 2.3 XML dictionary, JSON remapping, got 0

vs

CRITICAL:root:Expecting exactly 3 arguments; recog XML file, CPE 2.3 XML dictionary, JSON remapping, got 0

using

        logging.critical("Expecting exactly 3 arguments; recog XML file, CPE 2.3 XML dictionary, JSON remapping, got %s", len(sys.argv) - 1)
        exit(1)

update_cpes.py Outdated
else:
logging.error("Unexpected CPE %s", final_cpe_name)

return vp_map
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May want to add a sanity check here. If no records are imported from the XML then log an error and exit. Ran into this because it seems that I don't have the correct XML file.

@jhart-r7 jhart-r7 merged commit 6a798b1 into rapid7:master Aug 29, 2018
jhart-r7 added a commit that referenced this pull request Aug 29, 2018
@jhart-r7 jhart-r7 deleted the feature/cpes branch October 10, 2018 20:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants