An important part of vulnerability management is to understand and secure the supply chain of the software components that make up today's systems. Agile and DevOps teams make extensive use of open source libraries and frameworks to reduce development time and cost. But this medal also has a downside: the ability to inherit other people's mistakes and vulnerabilities.
Clearly, a team must be aware of what open source components are included in their applications, ensure that known trusted versions are downloaded from known trusted sources, and download updated versions of components after newly discovered vulnerabilities are patched.
In this post, we'll look at using the OWASP Dependency Check to abort a build if serious problems are found in your code.
In the book Development Security in Agile Projects, it is described as follows. OWASP Dependency Check is a free scanner that catalogs all open source components used in an application and shows the vulnerabilities they contain. Versions are available for Java, .NET, Ruby (gemspec), PHP (composer), Node.js, and Python, as well as some C/C++ projects. Dependency Check integrates with common build tools, including Ant, Maven, and Gradle, and continuous integration servers like Jenkins.
Dependency Check reports all components with known vulnerabilities from NIST's National Vulnerability Database (NVD) and is updated based on data from NVD news feeds.
Fortunately, all of this can be done automatically using tools such as the OWASP Dependency Check project or commercial programs such as
These tools can be included in build pipelines to automatically inventory open source dependencies, identify obsolete versions of libraries and libraries with known vulnerabilities, and abort the build if serious problems are found.
OWASP Dependency Check
To test and demonstrate the work of Dependency Check, we use this repository
To view the HTML report, you need to set up the nginx web server on your gitlab-runner.
An example of a minimal nginx config:
server {
listen 9999;
listen [::]:9999;
server_name _;
root /home/gitlab-runner/builds;
location / {
autoindex on;
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
At the end of the assembly, you can see this picture:
We follow the link and see the Dependency Check report.
The first screenshot is the top part of the report with a summary.
Second screenshot of CVE-2017-5638 details. Here we see the CVE level and links to exploits.
The third screenshot is the details of log4j-api-2.7.jar. We see that CVE levels 7.5 and 9.8.
The fourth screenshot is the details of commons-fileupload-1.3.2.jar. We see that CVE levels 7.5 and 9.8.
If you want to use gitlab pages, then it will not work - the dropped task will not create an artifact.
Example here
Assembly output: no artifacts, I don't see the html report. You should try Artifact: always
Adjustment of the level of CVE vulnerabilities
The most important line in the gitlab-ci.yaml file is:
mvn $MAVEN_CLI_OPTS test org.owasp:dependency-check-maven:check -DfailBuildOnCVSS=7
With the failBuildOnCVSS parameter, you can control the level of CVE vulnerabilities that you need to respond to.
Downloading the NIST Vulnerability Database (NVD) from the Internet
You have noticed that it constantly downloads the NIST Vulnerability Databases (NVD) from the Internet:
You can use the utility to download
Install and run it.
yum -y install yum-plugin-copr
yum copr enable antonpatsev/nist_data_mirror_golang
yum -y install nist-data-mirror
systemctl start nist-data-mirror
Nist-data-mirror uploads CVE JSON NIST to /var/www/repos/nist-data-mirror/ on startup and updates the data every 24 hours.
To download CVE JSON NIST, you need to set up an nginx web server (for example, on your gitlab-runner).
An example of a minimal nginx config:
server {
listen 12345;
listen [::]:12345;
server_name _;
root /var/www/repos/nist-data-mirror/;
location / {
autoindex on;
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
In order not to make a long line where mvn is launched, we will put the parameters into a separate variable DEPENDENCY_OPTS.
The final minimal .gitlab-ci.yml config will look like this:
variables:
MAVEN_OPTS: "-Dhttps.protocols=TLSv1.2 -Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=WARN -Dorg.slf4j.simpleLogger.showDateTime=true -Djava.awt.headless=true"
MAVEN_CLI_OPTS: "--batch-mode --errors --fail-at-end --show-version -DinstallAtEnd=true -DdeployAtEnd=true"
DEPENDENCY_OPTS: "-DfailBuildOnCVSS=7 -DcveUrlModified=http://localhost:12345/nvdcve-1.1-modified.json.gz -DcveUrlBase=http://localhost:12345/nvdcve-1.1-%d.json.gz"
cache:
paths:
- .m2/repository
verify:
stage: test
script:
- set +e
- mvn $MAVEN_CLI_OPTS install org.owasp:dependency-check-maven:check $DEPENDENCY_OPTS || EXIT_CODE=$?
- export PATH_WITHOUT_HOME=$(pwd | sed -e "s//home/gitlab-runner/builds//g")
- echo "************************* URL Dependency-check-report.html *************************"
- echo "http://$HOSTNAME:9999$PATH_WITHOUT_HOME/target/dependency-check-report.html"
- set -e
- exit ${EXIT_CODE}
tags:
- shell
Source: habr.com