Writing vulnerability checks

This is a tutorial on developing custom vulnerability checks in the Security Console. More information on this topic is available in the following articles:

The Security Console includes a framework for creating complex vulnerability checks using a simple XML format. Vulnerability checks are split across two or more files which are parsed by the Security Console when the Scan Engine starts.

There are 2 types of XML files that make up a vulnerability check:

  • Vulnerability descriptor - A file ending in the .xml extension which contains information about a specific vulnerability (title, description, severity, CVE IDs, CVSS score, etc.).
  • Vulnerability check - A file ending in the .vck extension containing multiple tests, which are compiled at runtime and used by the Security Console to verify the existence (or non-existence) of the vulnerability described in the descriptor.

One vulnerability can have several different types of checks (or .vcks) associated with it.

A third optional XML file type exists:

  • Vulnerability solution file - A file ending in the .sol extension which contains vulnerability solution information. This solution information may optionally be included in the vulnerability definition .xml file or broken out into a .sol for re-use for other vulnerabilities. Solutions contain information about how to remediate the vulnerability. A solution file allows the solution to be written once and updated in one place when the recommended solution changes for many vulnerabilities that use the same solution.

Create your first vulnerability check

In this article, we'll reimplement a simple vulnerability check from Nikto because it's an open source tool that many people will be familiar with. This example is based on a check added to Nikto for a WordPress version information leak. Let's do the same check in the Security Console so you can see the difference in approach.

The Nikto check is written as:

"006184","0","3","/wp-links-opml.php","GET","generator=\"WordPress/","","","","","This WordPress script reveals the installed version.","",""

In this check:

  • 006184 is the Nikto vulnerability ID
  • /wp-links-opml.php is the URL path to request
  • generator=\"WordPress/ is the string to look for in the response that would indicate the presence of this vulnerability (the quote is escaped in the Nikto file format)

Now let's create a check for the same vulnerability in the Security Console -- you'll find that the format is more complex and takes a bit longer to write (although internally here at Rapid7 we have authoring tools to speed up the process).

Create a vulnerability descriptor (.xml) file

First we create the .xml descriptor file. The file looks pretty complex, but it's actually fairly easy to explain. Create a file named cmty-http-wordpress-wplinks-opml-info-leak.xml with the following contents:

<?xml version='1.0' encoding='UTF-8'?>
<Vulnerability id="cmty-http-wordpress-wplinks-opml-info-leak" published="2007-05-26" added="2010-03-13" modified="2010-03-13" version="2.0">
<name>WordPress version information leak via wp-links-opml.php</name>
<id name="URL">http://blogsecurity.net/wordpress/tools/wp-scanner</id>
<p>The version of the WordPress blog software can be leaked by a request to
a file named wp-links-opml.php. This page outputs link information in OPML
format. OPML is the
<a href="http://en.wikipedia.org/wiki/OPML">Outline Processor Markup Language</a>,
used to exchange information between blog and RSS aggregators.</p>
<Solution id="cmty-http-wordpress-disable-wplinks-opml" time="30m">
<summary>Disable access to the wp-links-opml.php page</summary>
<p>Evaluate whether OPML needs to be enabled for your blog. If not, disable access to the wp-links-opml.php page by either
deleting it or by using your web server's access control mechanism (for example .htaccess on Apache) to disable HTTP access
to this file.</p>

Let's explain the different parts of this file:

  • The id attribute - Every vulnerability in the Security Console has a unique identifier. This ID distinguishes this vulnerability and is referred to by the corresponding .vck files (described below). In this case, the vulnerability ID is cmty-http-wordpress-wplinks-opml-info-leak. The cmty portion stands for "community". This prefix is used to keep this vulnerability from colliding with anything published by Rapid7.
    • Be aware that the XML file must have the same base name as the ID. The vulnerability ID contains a unique series of up to 255 alphabetic characters, numbers, or hyphens (-).
  • The published attribute - Vulnerabilities may have a published date which describes the date when information about the vulnerability was first released. This attribute is optional, although it is highly recommended to include the attribute if the information for the vulnerability is available. In this case we have chosen 2007-05-26 as our published date because that's the earliest reference I could find for this particular information leak. This attribute may contain a valid date in the form of YYYY-MM-DD.
  • The added attribute - The descriptor may have an added date, which is used to note when it was first included in the Security Console. In this case, the added date is 2010-03-13, which is the date this tutorial was originally written.
  • The modified attribute - This describes when this XML file was last modified.
    • If you modify the XML file, you must modify the modified attribute otherwise the Security Console will not re-process this file. If you want the Security Console to re-import this data into its internal database, you must change the modified attribute every time you change this file.
  • The version attribute - This attribute refers to the version of the vulnerability descriptor file format. This should always be set to 2.0.
  • The <name> element - The <name> element is the title of the vulnerability, as displayed in the vulnerability detail listing in the the Security Console UI and reports.
  • The <cvss> element - This element stores the complete CVSSv2 vector which scores this vulnerability. See http://www.first.org/cvss/cvss-guide.html for more information about CVSS.
    • The Security Console automatically computes the CVSS base score from the vector.
  • The <Tags> element - Tagging is used to categorize the vulnerability for purposes of category searching or customization of scan templates. I've given this vulnerability two tags: Web and WordPress.
  • The <AlternateIds> element - This element is used to group several reference identifiers to the vulnerability descriptor. These typically include references to Secunia advisories, CVE IDs, and URLs. The Security Console will automatically generate the correct hyperlink in the UI and reports for most types of IDs based on built-in logic. Alternate IDs can take several forms including:
    • <id name="BID">8725</id> for a Bugtraq ID
    • <id name="CVE">CVE-2002-1850</id> for a CVE ID
  • The <Description> element - This element is used to provide useful information on the behavior of the vulnerability which is displayed in the vulnerability details page in the UI. This element supports a limited subset of HTML markup, including <a>, <p>, <ul>, <ol>, and <li> so that it can be parsed into an intermediate documentation format, and subsequently be transformed into (X)HTML, PDF, RTF, and plaintext formats.
  • The <Solutions> element - This element describes "How can I patch or remediate this vulnerability?". The solutions for a vulnerability are grouped under the solutions element and are either referenced by id (for out-of-file solutions) or constructed in the file itself (inline solutions). The reason for solution IDs is so that the Remediation Report can automatically figure out how to optimize the remediation steps (for example, collapsing multiple vulnerabilities into a single common solution that remediates them all). The time attribute refers to the estimated amount of time it would take to follow the steps listed in the solution. You can use 30m to represent 30 minutes or 2h20m to represent 2 hours and 20 minutes.

Create a vulnerability check (.vck) file

Now create a file named cmty-http-wordpress-wplinks-opml-info-leak.vck with the following contents:

<VulnerabilityCheck id="cmty-http-wordpress-wplinks-opml-info-leak" scope="endpoint">
<NetworkService type="HTTP|HTTPS"/>
<HTTPRequest method="GET">
<HTTPResponse code="200">

Let's explain the different parts of this file:

  • The id attribute refers to the same ID used in the XML file. This tells the Security Console which vulnerability this check is meant for.
  • The scope attribute should be set to endpoint for service-specific vulnerabilities (those affecting a particular port or service) or node for system-wide vulnerabilities (those affecting the entire system). Web vulnerabilities are endpoint-specific by definition, while an exploit of the TCP/IP stack would be for the entire node.
  • The <NetworkService> element instructs the Scan Engine to run this check against any port found to be running the HTTP or HTTPS protocol. Notice the use of the | character (also known as a "pipe" character) to indicate HTTP or HTTPS.
  • This particular .vck uses the <HTTPCheck> element to indicate a basic HTTP "send a request, match the response" type of check. <HTTPCheck> may contain only one <HTTPRequest> child element and one <HTTPResponse> element. The <HTTPRequest> element may contain one or more <URI> elements. If multiple <URI> elements are present, each URI will be requested in turn, looking for a match to the <HTTPResponse> conditions.
  • The <HTTPResponse> element says "Look for a response with an HTTP status code of 200 whose body matches the given regular expression".
  • The <regex> element uses Perl 5 syntax, but with some small differences. This is matched against the HTTP response body. See http://nlp.stanford.edu/nlp/javadoc/gnu-regexp-docs/syntax.html for a complete syntax reference. If you want to do case-insensitive matching, specify <regex cflags="REG_ICASE">. Pattern matching occurs on a line-by-line basis. If you want the regex to match across multiple lines, specify <regex cflags="REG_LINE_ANY_CRLF">.

Deploy your vulnerability check

To deploy this vulnerability check, simply copy your .xml and corresponding .vck file into the following directory:


Next, access the Nexpose command console and run the load content command. Watch for errors on the console (look in nsc.log) when content is being reloaded. If you made any mistakes, the Security Console will log some error messages when it compiles the new vulnerabilities. If everything was successful, you should see something like the following message in the log:

2015-12-18T08:59:43 [INFO] Inserted 1 vulnerabilities.
2015-12-18T08:59:55 [INFO] Load Content command complete.

Finally, open the Vulnerabilities tab in your Security Console and access your new vulnerability check's details. The easiest way to do this is to append cmty-http-wordpress-wplinks-opml-info-leak to the /vulnerability/vuln-summary.jsp?vulnid= format in your browser's URL field. The following is an example of what this looks like (subsitute {console-address-or-domain} with the the correct IP address or FQDN of your console host):


You should see the details of your new vulnerability in this view. Review the information and correct any mistakes. Don't forget to re-deploy the file to the Security Console directory after you've made any necessary changes.

Run a scan with your new vulnerability

Your new vulnerability will automatically be included in most default scan templates. Simply run a scan against a server that has this vulnerability and see whether it shows up. The Security Console should show any new affected assets under the vulnerability.html page URL described above (don't forget to refresh the page). If the system is vulnerable but your check is not being detected, try running a Vulnerability Report Card report (with detail level set to High) for the affected asset(s) to see why the Security Console did not find the vulnerability.