Customizing policies checks in Rapid7’s Nexpose
Rapid7 Nexpose is one of the leading vulnerability assessment tools. It aims to support the entire vulnerability management life-cycle, including discovery, detection, verification, risk classification, impact analysis, reporting, mitigation and compliance check.
Nexpose offers a lot of functionalities one of them is the possibility to check if an asset is compliant or not with security standards such as “United States Government Configuration Baseline (USGCB)” or “Center for Internet Security (CIS)” via its policy manager. Where we can scan select a policy, assigne it to a template and scan our assets for compliance issues.
Sometimes when scanning for compliance issues, the checks used in those policies fall in the false positive / false negative trap and a need to modify these checks arises.
Our focus in this tutorial will be on the “Center for Internet Security (CIS)” benchmarks available in Nexpose policy manager (As they are the only type of policies i have tested. The same principle should apply to other policies).
How can one modify these policies if needed? In the case of false positives, false negatives or checks not working properly what can we do?
First, we need to create a copy on the policy that we want to modify because Nexpose won’t let us modify the built-in ones. To do that we navigate to the policies tab and select our policy (1) and select create copy (2) as shown below.
After that we connect via SSH to the Nexpose console and navigate to the following directory
We then search for the policy that we copied. The folder name should have this format [See below] and should be the most recently created one.
What is left is only compressing the folder and copying it to our local computer.
The policy folder have the following structure.
- CPE Dictionary XML: File containing the CPE list and items.
- CPE Oval XML: File containing the OVAL definitions for the CPE items referenced in the CEP Dictionary file.
- XCCDF Framework XML: File containing full details about each rule (check) in the policy. [For more information on the OVAL see this Link]
- Oval XML: File containing the OVAL definitions tests, objects, states and variables for each definition referenced in the XCCDF file. [For more information on the OVAL see this Link]
- Properties XML: /
Note: For the purpose of this tutorial, we will not be looking at how the OVAL language and XCCDF framework work in details. For more information, see the links referenced above.
Modifying an existing check
To start modifying checks we need to understand a little bit the structure of the XCCDF and the OVAL files. We will be looking at some of the tags available in these files and their purpose.
XCCDF file structure :
- <Benchmark>: This tag contains references for the xxcdf format and the style. However, more importantly it contains the ID of the benchmark. This ID will identify our policy inside of Nexpose so it must be unique.
- <Profile>: This will contain the following tags
- <title>: Title of the profile.
- <description>: Description of the profile.
- <select>: Each rule (check) defined in the file will be be referenced in the select tag. We can enable or disable any rule by modifying the “selected” attribute.
- <Value>: Will contain any variable needed in the checks and contains three sub tags <title>; <description>; <value>
- <Rule>: This is where we create the full description of our rule (check). It contains the following sub tags.
— <title>: The title of the rule.
— <description>: Description of the rule.
— <rationale>: The rationale behind this check (Why we need to check this).
— <fixtext>: A description on how to fix the issue if it’s not compliant
— <complex-check>: This is where we define the logic behind our check and put a reference to the OVAL’s definitions.
OVAL file structure :
A basic oval check is structured like this :
- <definition>: This where define our check with and it contains the following sub tags
— <title>: The title of the check.
— <description> : A little description of the check.
— <criteria> : contains criterion which references tests.
- <test>: This is where we define the type of check that we will execute (Read documentation for the complete list of possible tags). In general, it contains two tags objects and state.
- <object>: The command to be executed. It could be reading frome a file or executing a shell command.
- <state>: The excepted results after the execution.
Now that we understand a little bit of how both files are structured let’s look at a practical example. We’ll be looking at the “Centos 7 CIS Benchmark” and modifying the check “5.4.4. Ensure default user umask is 027 or more restrictive”.
First, we look for the check rule in the XCCDF file. We press Ctrl+F and search for the “5.4.4” string until we find the rule definition like so.
We scroll down until we reach the complex-check tag. This is where the check are defined and references to the OVAL definition are made. (See below)
We can see that there are four checks each one of them reference an OVAL definition.
Let us take for example the first check with the reference “1312”, navigate to the OVAL file, and search for it.
Ctrl + F the following string in the oval.xml file: “oval:org.cisecurity.benchmarks.o_centos_centos:def:1312”
If we follow the OVAL structure cited before, next thing we need to look for is the criteria tag to get the test executed by this check. Colored in red in the image above is the criterion (test reference) for this check.
To understand what this test will do we need lookup the tag <textfilecontent54_test>.
According to the documentation, this tag is used to read from a text file and check its content (See documentation of OVAL). We can also read the comment attribute on this test to get a grasp of its functionality.
This test references the object “oval:org.cisecurity.benchmarks.o_centos_centos:obj:10326” that we are going to look at next.
The final piece of this check is the object definition, which includes all the details needed to execute this check. The documentation describe the object as follows:
The textfilecontent54_object element is used by a textfilecontent_test to define the specific block(s) of text of a file(s) to be evaluated
- <ind:filepath>: Indicates the file that we’re going to evaluate.
- <ind:pattern>: Indicates the pattern / regex that we’re going to apply.
- <ind:instance>: The documentation explains it best and it’s as follows.
The instance entity calls out a specific match of the pattern. The first match is given an instance value of 1, the second match is given an instance value of 2, and so on.
Our modification comes at this level. If we don’t like the pattern or want to enforce a more restrictive check we can change the pattern to our need. (In the general case, we also modify in the state definition the expected output but it’s not the case with this check).
After we’ve completed our modifications, comes the final step that is uploading our new policy to the Nexpose console.
Uploading the modified policy :
Before uploading the new policy, we need to make sure that we’ve modified the policy ID. To do that we navigate to the XCCDF file and at the top of the file there is the Benchmark tag containing the ID attribute.
Generally, I add the word “custom” at the end of the original ID and that will do the trick.
Next, we need to compress all the files into a single zip file and get ready to upload. We navigate to the Nexpose console and the policy tab and select upload policy.
That is it. The new policy should be available in the policy view and can be used in templates to scan our assets.
Thanks for reading.
Questions? Comments? Contact me via twitter @nas_bench