By Niren Shah
The world of software development can be very convoluted -- especially when your code is dependent on hundreds of 3rd party libraries and scripts. Fortunately, we have build tools that automate a lot of the ground work for us (Maven, Gradle, Jenkins, etc.). But the problem comes when you have no idea what all dependencies get pulled in "automagically" -- including one that possibly might have vulnerabilities that are exploitable. This is such a common problem that it made #9 on the OWASP Top 10 list.
Fortunately there are ways to mitigate this problem and OWASP itself has a tool that helps with this. It is called Dependency Check. It supports Java and .NET and few other technologies in experimental form. It does exactly what you'd think it does: it identifies all the projects' dependencies and checks them against any publicly disclosed vulnerabilities.
Here is a simple example to show you how it works and how you might be able to integrate it into your continuous development and build cycle.
Let's say we had a simple Spring Boot project. It can be anything but I used Spring Boot because it pulls in a decent number of dependencies and makes for a better report :). So the simplistic build.gradle file looks like this:
buildscript {
ext {
springBootVersion = '2.0.2.RELEASE'
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradleplugin:${springBootVersion}")
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
compile('org.springframework.boot:spring-boot-starter')
testCompile('org.springframework.boot:spring-boot-starter-test')
}
Now, in order to add the dependency check plugin, we simply add the following 2 lines (in bold) to the build file:
buildscript {
<...>
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
classpath('org.owasp:dependency-check-gradle:3.1.2')
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
apply plugin: 'org.owasp.dependencycheck'
<...>
And that's it! You can run the dependency check tool via the following command and it will pull the vulnerability database and check all your dependencies against those and lets you know if it found anything. It'll also generate a report in the build directory that you can view. Here it didn't find any vulnerabilities.
./gradlew dependencyCheckAnalyze
> Task :dependencyCheckAnalyze
Verifying dependencies for project demo
Checking for updates and analyzing vulnerabilities for dependencies
Generating report for project demo
Found 0 vulnerabilities in project demo
BUILD SUCCESSFUL in 3s
1 actionable task: 1 executed
Let's do something fun :). Commons BeanUtils is a pretty popular library among Java developers. And it has a known vulnerability for certain versions. So, to test this out, we add that to our project as such:
<...>
dependencies {
compile('org.springframework.boot:spring-boot-starter')
compile('commons-beanutils:commons-beanutils:1.8.0')
testCompile('org.springframework.boot:spring-boot-starter-test')
}
<...>
And then we run the dependency check again. There you go: it tells you that it found 1 vulnerability in our project and points you to the CVE ID. It will also generate the full report for you. See below for a sample.
./gradlew dependencyCheckAnalyze
> Task :dependencyCheckAnalyze
Verifying dependencies for project demo
Checking for updates and analyzing vulnerabilities for dependencies
Generating report for project demo
Found 1 vulnerabilities in project demo
One or more dependencies were identified with known vulnerabilities:
commons-beanutils-1.8.0.jar (commons-beanutils:commons-beanutils:1.8.0, cpe:/a:apache:commons_beanutils:1.8.0) : CVE-2014-0114
See the dependency-check report for more details.
BUILD SUCCESSFUL in 3s
1 actionable task: 1 executed
If you accidentally end up pulling in a vulnerable dependency, why not fail your builds before they get deployed?
Thoughts?