sorenpoulsen.com header

Using OWASP Dependency Check with Maven

Using software components with known security vulnerabilities is a class of security risk listed at rank 9 on the OWASP Top 10 Security Risks for 2017. A recent example is the company Equifax that suffered a massive data breach affecting more than 145 mio. people. Equifax failed to apply a security patch for the Apache Struts2 web framework for several months despite their own policy to apply patches no later than 48 hours after their disclosure.

The data breach included social security numbers which means that half the US population are now the potential target of identity thieves.

OWASP incidentally has a free tool OWASP DependencyCheck that detects the use of vulnerable components and as we shall see in this post, it also detects the vulnerability known as CVE-2017-5638 in Apache Struts2 that is the cause of Equifax's predicament.

Integrating OWASP DependecyCheck in a software project built with Apache Maven is fairly straight forward, so let's dig in.

Add the OWASP DependecyCheck plugin to a Maven project

Add dependency-check-maven plugin to the project's pom.xml file.

Run the dependency check

Run the plugin's check goal.

$ mvn test org.owasp:dependency-check-maven:check
...
[INFO] --- dependency-check-maven:2.1.1:check (default-cli) @ TestDependencyCheck ---
[INFO] No dependencies were identified that could be analyzed by dependency-check
[INFO] Checking for updates
[INFO] starting getUpdatesNeeded() ...
[INFO] NVD CVE requires several updates; this could take a couple of minutes.
[INFO] Download Started for NVD CVE - 2003
[INFO] Download Started for NVD CVE - 2002
[INFO] Download Started for NVD CVE - 2007
[INFO] Download Started for NVD CVE - 2005
[INFO] Download Started for NVD CVE - 2004
[INFO] Download Started for NVD CVE - 2006
[INFO] Download Complete for NVD CVE - 2003  (4174 ms)
[INFO] Download Started for NVD CVE - 2008
[INFO] Processing Started for NVD CVE - 2003
[INFO] Download Complete for NVD CVE - 2004  (5513 ms)
[INFO] Download Started for NVD CVE - 2009
[INFO] Processing Started for NVD CVE - 2004
[INFO] Processing Complete for NVD CVE - 2003  (1863 ms)
[INFO] Download Complete for NVD CVE - 2005  (6441 ms)
[INFO] Download Started for NVD CVE - 2010
[INFO] Processing Started for NVD CVE - 2005
[INFO] Processing Complete for NVD CVE - 2004  (1963 ms)
[INFO] Download Complete for NVD CVE - 2007  (8092 ms)
[INFO] Download Started for NVD CVE - 2011
[INFO] Processing Started for NVD CVE - 2007
[INFO] Download Complete for NVD CVE - 2006  (8746 ms)
[INFO] Processing Started for NVD CVE - 2006
[INFO] Download Started for NVD CVE - 2012
[INFO] Processing Complete for NVD CVE - 2005  (3144 ms)
[INFO] Download Complete for NVD CVE - 2002  (11534 ms)
[INFO] Processing Started for NVD CVE - 2002
[INFO] Download Started for NVD CVE - 2013
[INFO] Download Complete for NVD CVE - 2008  (8114 ms)
[INFO] Processing Started for NVD CVE - 2008
[INFO] Download Started for NVD CVE - 2014
[INFO] Download Complete for NVD CVE - 2009  (7702 ms)
[INFO] Download Started for NVD CVE - 2015
[INFO] Processing Complete for NVD CVE - 2007  (7395 ms)
[INFO] Processing Started for NVD CVE - 2009
[INFO] Download Complete for NVD CVE - 2010  (9861 ms)
[INFO] Download Started for NVD CVE - 2016
[INFO] Processing Complete for NVD CVE - 2006  (9615 ms)
[INFO] Processing Started for NVD CVE - 2010
[INFO] Download Complete for NVD CVE - 2012  (9792 ms)
[INFO] Download Started for NVD CVE - 2017
[INFO] Processing Complete for NVD CVE - 2002  (7566 ms)
[INFO] Processing Started for NVD CVE - 2012
[INFO] Download Complete for NVD CVE - 2013  (12117 ms)
[INFO] Download Started for NVD CVE - Modified
[INFO] Download Complete for NVD CVE - 2015  (10612 ms)
[INFO] Download Complete for NVD CVE - 2014  (12614 ms)
[INFO] Download Complete for NVD CVE - 2016  (10442 ms)
[INFO] Download Complete for NVD CVE - 2011  (19551 ms)
[INFO] Download Complete for NVD CVE - Modified  (7219 ms)
[INFO] Download Complete for NVD CVE - 2017  (13710 ms)
[INFO] Processing Complete for NVD CVE - 2009  (17274 ms)
[INFO] Processing Started for NVD CVE - 2013
[INFO] Processing Complete for NVD CVE - 2008  (21717 ms)
[INFO] Processing Started for NVD CVE - 2015
[INFO] Processing Complete for NVD CVE - 2010  (23019 ms)
[INFO] Processing Started for NVD CVE - 2014
[INFO] Processing Complete for NVD CVE - 2012  (24867 ms)
[INFO] Processing Started for NVD CVE - 2016
[INFO] Processing Complete for NVD CVE - 2013  (21390 ms)
[INFO] Processing Started for NVD CVE - 2011
[INFO] Processing Complete for NVD CVE - 2015  (25555 ms)
[INFO] Processing Started for NVD CVE - Modified
[INFO] Processing Complete for NVD CVE - 2014  (36331 ms)
[INFO] Processing Started for NVD CVE - 2017
[INFO] Processing Complete for NVD CVE - 2016  (37048 ms)
[INFO] Processing Complete for NVD CVE - Modified  (33684 ms)
[INFO] Processing Complete for NVD CVE - 2011  (40076 ms)
[INFO] Processing Complete for NVD CVE - 2017  (17620 ms)
[INFO] Begin database maintenance.
[INFO] End database maintenance.
[INFO] Check for updates complete (101670 ms)
[INFO] Analysis Started
[INFO] Finished File Name Analyzer (0 seconds)
[INFO] Finished Central Analyzer (0 seconds)
[INFO] Finished Dependency Merging Analyzer (0 seconds)
[INFO] Finished Version Filter Analyzer (0 seconds)
[INFO] Finished Hint Analyzer (0 seconds)
[INFO] Created CPE Index (2 seconds)
[INFO] Finished CPE Analyzer (2 seconds)
[INFO] Finished False Positive Analyzer (0 seconds)
[INFO] Finished Cpe Suppression Analyzer (0 seconds)
[INFO] Finished NVD CVE Analyzer (0 seconds)
[INFO] Finished Vulnerability Suppression Analyzer (0 seconds)
[INFO] Finished Dependency Bundling Analyzer (0 seconds)
[INFO] Analysis Complete (2 seconds)

The plugin downloads all the known Common Vulnerabilities and Exposures (CVE) from the National Vulnerability Database (NVD) and stores them in the Maven repository under /.m2/repository/org/owasp/dependency-check-data/3.0/dc.h2.db.

It then proceeds to analyze the Maven project's dependencies. All vulnerable dependencies are listed directly in the console output.

On subsequent runs the plugin will only download updates from NVD.

The projects pom.xml shown previously doesn't have any dependencies other that the plugin itself. To spice things up let's add Apache Struts2 version 2.5.10 as a dependency in our project.

Run the dependency checker again.

$ mvn test org.owasp:dependency-check-maven:check
...
[WARNING] One or more dependencies were identified with known vulnerabilities in TestDependencyCheck:

commons-fileupload-1.3.2.jar (commons-fileupload:commons-fileupload:1.3.2, cpe:/a:apache:commons_fileupload:1.3.2) : CVE-2016-1000031
log4j-api-2.7.jar (cpe:/a:apache:log4j:2.7, org.apache.logging.log4j:log4j-api:2.7) : CVE-2017-5645
struts2-core-2.5.10.jar (cpe:/a:apache:struts:2.5.10, org.apache.struts:struts2-core:2.5.10) : CVE-2017-9805, CVE-2017-9804, CVE-2017-9793, CVE-2017-9787, CVE-2017-7672, CVE-2017-5638, CVE-2017-12611

So this time around the dependency checker detects multiple vulnerabilities, including CVE-2017-5638.

The OWASP DependencyCheck report

We could google each CVE listed, but the dependency checker has already prepared a report with all the details. The report is stored in target/dependency-check-report.html.

screenshot of OWASP DependencyCheck report

In addition to listing the vulnerable dependencies that we already saw in the output from Maven, we can see the details of each vulnerability further down the page. Try scrolling to the vulnerability CVE-2017-5638.

screenshot of OWASP DependencyCheck report

From the description we learn that an attacker can execute code on the server by simply passing the code through the HTTP header "Content-Type". Typically an attacker would send code that starts a new shell process and link it up with a Servlet that interactively pipes commands through HTTP to the shell. Because of the ease of exploiting this vulnerability and the level of compromise, it has the highest score of 10.0 in the Common Vulnerability Scoring System (CVSS).

False positives

The dependency checker detects the use of known vulnerabilities by looking for matches of the dependencies in the Maven project with the software components listed in the CVEs. This process is a little sketchy because they have different schemes for identifying software. Maven identifies dependencies using GroupId, ArtifactId and Version (GAV) and CVEs identify software using Common Platform Enumeration (CPE).

Scrolling back to the list of vulnerable dependencies we find a column named CPE Confidence. This is a score of how confident the dependency checker is that it made a correct match.

In the case of the Struts2-core-2.5.10.jar dependency the CPE Confidense is "Highest". To any human being reading the description it is obvious that this is indeed a match but we will often have false positives. So regardless of the CPE Confidense it is always prudent to read through the CVE description and make our own conclusions.

To prevent false positives from reappearing we can suppress either the software component identified by the CPE or the individual vulnerability by clicking the Suppress button in the report and saving the XML snippet to a file in the project. The first time select the output from "Complete XML Doc". Say we stored the XML in the root of the Maven project in a file named suppressed.xml we would then configure the dependency checker to use this file using the suppressionFiles option in the pom.xml.

Activating the dependency checker with a Maven profile

Rather than naming the dependency checker plugin and the check goal on the commandline, we can bind the goal to a Maven build phase and wrap it in a Maven profile thats easier to remember.

In this example the profile is named securitycheck.

Use the -P option to activate the profile.

$ mvn clean install -Psecuritycheck

Fail the build when vulnerabilities are detected

To make sure detected vulnerabilities don't go unnoticed we could set up a automated Jenkins job to run the dependency checker regularly and configure the plugin to fail the build when vulnerabilities are detected.

The following pom.xml fails on any vulnerability by setting the configuration property failBuildOnAnyVulnerability to true. Alternatively we could use the failBuildOnCVSS to fail on a CVSS score above a certain threshold.

{{model.usr.name}}
{{cmt.user.name}}
{{cmt.user.name}}
{{childcmt.user.name}}
{{childcmt.user.name}}