Subscribe to the feed

In a previous article, I showed you how to detect third-party vulnerabilities in Python. This article shows how to scan your Java code for the same issues.

Example 1: Scan the libraries of an open source project

Software is complex, but thanks to open source, I can quickly develop new applications by leveraging the efforts of people who choose to share their work. Unfortunately, new software functionality also introduces new bugs that malicious attackers could exploit.

To illustrate the problem, I will download a vulnerable version of a well-known open source application server:

$ curl --location --fail --output ~/Downloads/XXXX-A.B.C-zzzz.zip https://XXX.ZZZZ.org/dist/XXX/server/A.B.C/XXXX-A.B.C-zzzz.zip
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 88.8M  100 88.8M    0     0  5142k      0  0:00:17  0:00:17 --:--:-- 1194k

cd ~/Downloads
unzip XXXX-A.B.C-zzzz.zip

There are many tools out there to scan for application vulnerabilities. I will demonstrate how to do this with OWASP dependency analyzer by Jeremy Long, so grab a copy:

$ curl --fail --output ~/Downloads/dependency-check-6.5.3-release.zip --location https://github.com/jeremylong/DependencyCheck/releases/download/v6.5.3/dependency-check-6.5.3-release.zip
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   669  100   669    0     0   4430      0 --:--:-- --:--:-- --:--:--  4430
100 23.0M  100 23.0M    0     0  7653k      0  0:00:03  0:00:03 --:--:-- 8899k

Use it to check vulnerabilities on this application:

$ ~/Downloads/dependency-check/bin/dependency-check.sh --prettyPrint --format HTML -scan /home/josevnz/Downloads/XXXX-A.B.C-zzzz/lib/
[INFO] Checking for updates
[INFO] Download Started for NVD CVE - Modified
[INFO] Download Complete for NVD CVE - Modified  (278 ms)
[INFO] Processing Started for NVD CVE - Modified
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by com.fasterxml.jackson.module.afterburner.util.MyClassLoader (file:/home/josevnz/Downloads/dependency-check/lib/jackson-module-afterburner-2.13.1.jar) to method java.lang.ClassLoader.findLoadedClass(java.lang.String)
WARNING: Please consider reporting this to the maintainers of com.fasterxml.jackson.module.afterburner.util.MyClassLoader
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
[INFO] Processing Complete for NVD CVE - Modified  (5150 ms)
[INFO] Begin database maintenance
[INFO] Updated the CPE ecosystem on 116793 NVD records
[INFO] Cleaned up 2 orphaned NVD records
[INFO] End database maintenance (24739 ms)
[INFO] Begin database defrag
[INFO] End database defrag (4660 ms)
[INFO] Check for updates complete (39967 ms)
[INFO] 

Dependency-Check is an open source tool performing a best effort analysis of 3rd party dependencies; false positives and false negatives may exist in the analysis performed by the tool. Use of the tool and the reporting provided constitutes acceptance for use in an AS IS condition, and there are NO warranties, implied or otherwise, with regard to the analysis or its use. Any use of the tool and the reporting provided is at the user's risk. In no event shall the copyright holder or OWASP be held liable for any damages whatsoever arising out of or in connection with the use of this tool, the analysis performed, or the resulting report.

   About ODC: https://jeremylong.github.io/DependencyCheck/general/internals.html
   False Positives: https://jeremylong.github.io/DependencyCheck/general/suppression.html

đź’– Sponsor: https://github.com/sponsors/jeremylong


[INFO] Analysis Started
[INFO] Finished Archive Analyzer (1 seconds)
[INFO] Finished File Name Analyzer (0 seconds)
[INFO] Finished Jar Analyzer (1 seconds)
[INFO] Finished Central Analyzer (9 seconds)
[ERROR] ----------------------------------------------------
[ERROR] .NET Assembly Analyzer could not be initialized and at least one ''exe'' or ''dll'' was scanned. The ''dotnet'' executable could not be found on the path; either disable the Assembly Analyzer or add the path to dotnet core in the configuration.
[ERROR] ----------------------------------------------------
[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 (6 seconds)
[INFO] Finished False Positive Analyzer (0 seconds)
[INFO] Finished NVD CVE Analyzer (0 seconds)
[INFO] Finished Sonatype OSS Index Analyzer (3 seconds)
[INFO] Finished Vulnerability Suppression Analyzer (0 seconds)
[INFO] Finished Dependency Bundling Analyzer (0 seconds)
[INFO] Analysis Complete (23 seconds)
[INFO] Writing report to: /home/josevnz/Downloads/./dependency-check-report.html
OWASP scan results

The report shows that the version I chose has several issues. The vendor fixed all of them in the latest release.

Not everything is perfect, and the tool could generate false positives, but this is still a great start.

Next, I'll show a different project that you can fix yourself.

Example 2: Analyze a homegrown Covid-19 town statistics reporter

This project downloads Covid-19 data from the State of Connecticut government portal and performs basic filtering before displaying the results.

Download and compile with Gradle:

git clone   https://github.com/josevnz/Covid19Informer.git
$ gradle test jar 
$ gradle distTar
$ /bin/tar --directory $HOME --extract --verbose --file build/distributions/Covid19Informer-0.0.1.tar

NOTE: You could also install by hand like this (I like the Gradle wrapper enough to avoid doing this):

/bin/mkdir --parent --verbose $HOME/Covid19Informer-0.0.1
/bin/cp --verbose build/libs/Covid19Informer-0.0.1.jar $HOME/Covid19Informer-0.0.1
/bin/curl --fail --location --output $HOME/Covid19Informer-0.0.1/lanterna-3.1.1.jar --url https://repo1.maven.org/maven2/com/googlecode/lanterna/lanterna/3.1.1/lanterna-3.1.1.jar
/bin/curl --fail --location --output $HOME/Covid19Informer-0.0.1/commons-io-2.11.0.jar --url https://repo1.maven.org/maven2/commons-io/commons-io/2.11.0/commons-io-2.11.0.jar

Next, run Covid19Informer to get an idea of what this small application does. I usually won't use an Uber .jar in production, but instead will deploy the Java application and its dependencies (jars) in a deployment directory:

$ $HOME/Covid19Informer-0.0.1/bin/Covid19Informer
...
INFO: Covid19DataPerTown[lastUpdateDate=2022-01-19, townNumber=135, town='Stamford', totalCases=26239, confirmedCases=24448, probableCases=1791, caseRate=135.0, totalDeaths=349, confirmedDeaths=308, probableDeaths=41, peopleTested=121435, rateTestedPer100k=93672.0, numberOfTests=383071, numberOfPositives=33471, numberOfNegatives=308, numberOfIndeterminates=422]
Jan 20, 2022 7:39:13 PM com.kodegeek.covid19.towndata.TownDataRetriever$Covid19DataPerTown lambda$printCovidData$1
INFO: Covid19DataPerTown[lastUpdateDate=2022-01-19, townNumber=151, town='Waterbury', totalCases=29064, confirmedCases=25500, probableCases=3564, caseRate=151.0, totalDeaths=444, confirmedDeaths=378, probableDeaths=66, peopleTested=99611, rateTestedPer100k=92603.0, numberOfTests=423805, numberOfPositives=36882, numberOfNegatives=378, numberOfIndeterminates=787]

Analyze the dependencies:

$ ~/Downloads/dependency-check/bin/dependency-check.sh --prettyPrint --format HTML -scan $HOME/Covid19Informer-0.0.1/lib
[INFO] Checking for updates
[INFO] Skipping NVD check since last check was within 4 hours.
[INFO] Skipping RetireJS update since last update was within 24 hours.
[INFO] Check for updates complete (62 ms)
[INFO] 

Dependency-Check is an open source tool performing a best effort analysis of 3rd party dependencies; false positives and false negatives may exist in the analysis performed by the tool. Use of the tool and the reporting provided constitutes acceptance for use in an AS IS condition, and there are NO warranties, implied or otherwise, with regard to the analysis or its use. Any use of the tool and the reporting provided is at the user'suser's risk. In no event shall the copyright holder or OWASP be held liable for any damages whatsoever arising out of or in connection with the use of this tool, the analysis performed, or the resulting report.

   About ODC: https://jeremylong.github.io/DependencyCheck/general/internals.html
   False Positives: https://jeremylong.github.io/DependencyCheck/general/suppression.html

đź’– Sponsor: https://github.com/sponsors/jeremylong

[INFO] Analysis Started
[INFO] Finished Archive Analyzer (0 seconds)
[INFO] Finished File Name Analyzer (0 seconds)
[INFO] Finished Jar 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 (1 seconds)
[INFO] Finished CPE Analyzer (2 seconds)
[INFO] Finished False Positive Analyzer (0 seconds)
[INFO] Finished NVD CVE Analyzer (0 seconds)
[INFO] Finished Sonatype OSS Index Analyzer (0 seconds)
[INFO] Finished Vulnerability Suppression Analyzer (0 seconds)
[INFO] Finished Dependency Bundling Analyzer (0 seconds)
[INFO] Analysis Complete (2 seconds)
[INFO] Writing report to: /home/josevnz/Documents/Covid19Informer/./dependency-check-report.html

The application is clean, but that doesn't mean I caught all the issues. Let me elaborate:

  • I didn't check the test or integration dependencies, if any. I checked only the runtime dependencies (which is good enough for most cases).
  • This approach is reactive, meaning I'll catch a problem after it happens, not during the development cycle.

The situation improves when I have access to the source code.

[ Download the eBook to Get ready for your Red Hat remote exam. ]

Example 3: Scan Covid19Informer while compiling the code

To use the tool as part of continuous integration, add it into the build.gradle.kts.

plugins {
    `java-library`
    application
    id("org.owasp.dependencycheck") version "6.5.3"
}

Using it is just a matter of calling Gradle, like this:

$ gradle dependencyCheckAnalyze --info
...
One or more dependencies were identified with known vulnerabilities in Covid19Informer:

h2-1.4.199.jar (pkg:maven/com.h2database/h2@1.4.199, cpe:2.3:a:h2database:h2:1.4.199:*:*:*:*:*:*:*) : CVE-2021-23463, CVE-2021-42392

See the dependency-check report for more details.

Element event queue destroyed: org.apache.commons.jcs.engine.control.event.ElementEventQueue@12440215
In DISPOSE, [NODEAUDIT] fromRemote [false]
In DISPOSE, [NODEAUDIT] auxiliary [NODEAUDIT]
...
BUILD SUCCESSFUL in 4s
2 actionable tasks: 2 executed
Some of the file system contents retained in the virtual file system are on file systems that Gradle doesn't support watching. The relevant state was discarded to ensure changes to these locations are properly detected. You can override this by explicitly enabling file system watching.
Watching 24 directories to track changes

A few things to note:

  • The build went through, but there was a warning: A vulnerable .jar was found in my Gradle cache (file path: /home/josevnz/.gradle/caches/modules-2/files-2.1/com.h2database/h2/1.4.199/7bf08152984ed8859740ae3f97fae6c72771ae45/h2-1.4.199.jar). It is there from a previous test, so keep this in mind if you run into some false positives when using this tool.
  • This Gradle scanner downloads a lot of data the first time. After that, it stabilizes using the local cache content.

For that reason, I'll show you a different Gradle plugin to scan for vulnerabilities.

[ Learn the benefits of modernizing your network in the eBook Network automation for everyone. ]

Example 4: Use a different tool to scan Covid19Informer after it is compiled

The folks from Sonatype created a Gradle plugin to scan your project called Scan Gradle Plugin, which is baked in by the OSS Index catalog.

By now, you can probably see where this is going. By having this check within your Java compilation toolset, your continuous integration tool can run this scan every time the code changes, reporting any anomalies back to you before the code is deployed into production.

To make this happen, add the following to the build.gradle.kts file:

plugins {
    `java-library`
    id ("org.sonatype.gradle.plugins.scan") version "2.2.2"
}

ossIndexAudit {
    username = System.getenv("ossindexaudit_user")
    password = System.getenv("ossindexaudit_password")
}

And then scan for vulnerabilities (Sonatype recommends creating a free account with no limits on the number of times you call the service):

$ gradlew test jar
# These 2 variables will be ''injected'' on your continuous integration environment
$ read -r -p "Please enter your Sonatype user (like myemail@example.com): " ossindexaudit_user
$ read -r -p -s ""Please enter your Sonatype account password"" ossindexaudit_user
$ export ossindexaudit_user ossindexaudit_user
$ gradle ossIndexAudit 

> Task :ossIndexAudit
 ________  ________  ________  ________  ___       _______           ________  ________  ________  ________
|\   ____\|\   __  \|\   __  \|\   ___ \|\  \     |\  ___ \         |\   ____\|\   ____\|\   __  \|\   ___  \
\ \  \___|\ \  \|\  \ \  \|\  \ \  \_|\ \ \  \    \ \   __/|        \ \  \___|\ \  \___|\ \  \|\  \ \  \\ \  \
 \ \  \  __\ \   _  _\ \   __  \ \  \ \\ \ \  \    \ \  \_|/__       \ \_____  \ \  \    \ \   __  \ \  \\ \  \
  \ \  \|\  \ \  \\  \\ \  \ \  \ \  \_\\ \ \  \____\ \  \_|\ \       \|____|\  \ \  \____\ \  \ \  \ \  \\ \  \
   \ \_______\ \__\\ _\\ \__\ \__\ \_______\ \_______\ \_______\        ____\_\  \ \_______\ \__\ \__\ \__\\ \__\
    \|_______|\|__|\|__|\|__|\|__|\|_______|\|_______|\|_______|       |\_________\|_______|\|__|\|__|\|__| \|__|
                                                                       \|_________|


  _      _                       _   _
 /_)    /_`_  _  _ _/_   _  _   (/  /_`_._  _   _/ _
/_)/_/ ._//_// //_|/ /_//_//_' (_X /  ///_'/ //_/_\
   _/                _//

Gradle Scan version: 2.2.2
------------------------------------------------------------------------------------------------------------------------------------------------------

Checking vulnerabilities in 1 dependencies
No vulnerabilities found!

BUILD SUCCESSFUL in 758ms
1 actionable task: 1 executed

So everything is good, right?

Not quite. Take a closer look at my project again:

dependencies {
    implementation("com.googlecode.lanterna:lanterna:3.1.1")
    implementation("commons-cli:commons-cli:20040117.000000")
    testImplementation("junit:junit:4.13")
}

The scanner found my compilation dependencies but ignored my testing dependencies—in this case, Junit. It turns out the version I'm using on my build file has a vulnerability from 2020: JUnit CVE-2020-15250.

Why did that happen? You need to have the isAllConfigurations = true property set to true on the build.gradle.kts:

ossIndexAudit {
    username = System.getenv("ossindexaudit_user")
    password = System.getenv("ossindexaudit_password")
    isAllConfigurations = true
}

I'll try again:

$ gradle jar; gradle ossIndexAudit 

BUILD SUCCESSFUL in 2s
3 actionable tasks: 3 up-to-date

> Task :ossIndexAudit FAILED
 ________  ________  ________  ________  ___       _______           ________  ________  ________  ________
|\   ____\|\   __  \|\   __  \|\   ___ \|\  \     |\  ___ \         |\   ____\|\   ____\|\   __  \|\   ___  \
\ \  \___|\ \  \|\  \ \  \|\  \ \  \_|\ \ \  \    \ \   __/|        \ \  \___|\ \  \___|\ \  \|\  \ \  \\ \  \
 \ \  \  __\ \   _  _\ \   __  \ \  \ \\ \ \  \    \ \  \_|/__       \ \_____  \ \  \    \ \   __  \ \  \\ \  \
  \ \  \|\  \ \  \\  \\ \  \ \  \ \  \_\\ \ \  \____\ \  \_|\ \       \|____|\  \ \  \____\ \  \ \  \ \  \\ \  \
   \ \_______\ \__\\ _\\ \__\ \__\ \_______\ \_______\ \_______\        ____\_\  \ \_______\ \__\ \__\ \__\\ \__\
    \|_______|\|__|\|__|\|__|\|__|\|_______|\|_______|\|_______|       |\_________\|_______|\|__|\|__|\|__| \|__|
                                                                       \|_________|


  _      _                       _   _
 /_)    /_`_  _  _ _/_   _  _   (/  /_`_._  _   _/ _
/_)/_/ ._//_// //_|/ /_//_//_' (_X /  ///_'/ //_/_\
   _/                _//

Gradle Scan version: 2.2.2
------------------------------------------------------------------------------------------------------------------------------------------------------

Checking vulnerabilities in 2 dependencies
Found vulnerabilities in 1 dependencies
[1/1] - pkg:maven/junit/junit@4.7 - 1 vulnerability found!

   Vulnerability Title:  [CVE-2020-15250] In JUnit4 from version 4.7 and before 4.13.1, the test rule TemporaryFolder cont...
   ID:  7ea56ad4-8a8b-4e51-8ed9-5aad83d8efb1
   Description:  In JUnit4 from version 4.7 and before 4.13.1, the test rule TemporaryFolder contains a local information disclosure vulnerability. On Uni...
   CVSS Score:  (5.5/10, Medium)
   CVSS Vector:  CVSS:3.0/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:N/A:N
   CVE:  CVE-2020-15250
   Reference:  https://ossindex.sonatype.org/vulnerability/7ea56ad4-8a8b-4e51-8ed9-5aad83d8efb1?component-type=maven&component-name=junit.junit&utm_source=ossindex-client&utm_medium=integration&utm_content=1.7.0


FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':ossIndexAudit'.
> Vulnerabilities detected, check log output to review them

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

Deprecated Gradle features were used in this build, making it incompatible with Gradle 8.0.
Use ''--warning-mode all'' to show the individual deprecation warnings.
See https://docs.gradle.org/7.0/userguide/command_line_interface.html#sec:command_line_warnings

BUILD FAILED in 1s
1 actionable task: 1 executed

Great! Fixing this is trivial—just upgrade Junit to the latest coordinates (at this time junit:junit:4.13.2) in build.gradle.kts and compile it again:

dependencies {
    implementation("com.googlecode.lanterna:lanterna:3.1.1")
    implementation("commons-io:commons-io:2.11.0")
    testImplementation("junit:junit:4.13.2")
}
Checking vulnerabilities in 3 dependencies
No vulnerabilities found!

Deprecated Gradle features were used in this build, making it incompatible with Gradle 8.0.
Use ''--warning-mode all'' to show the individual deprecation warnings.
See https://docs.gradle.org/7.0/userguide/command_line_interface.html#sec:command_line_warnings

BUILD SUCCESSFUL in 2s
1 actionable task: 1 executed

Will an IDE tell if you are using an older version of a library?

Most integrated development environments (IDEs) will report these issues, and you should not ignore those warnings. For example, the Community Edition of IntelliJ caught the old Junit and marked my build.gradle.kts file with a warning:

intellij_gradle_warning

Other IDEs—like VS Code—do the same.

What you've learned

  • How to analyze projects using OWASP Dependency check.
  • How to fix projects if a vulnerable dependency is found (in this case by fixing the build.gradle.kts file).
  • How to add vulnerability checks to your continuous integration using the sonatype-scan-gradle-plugin.

Now you are more prepared to check your Java projects for third-party vulnerabilities.


About the author

Proud dad and husband, software developer and sysadmin. Recreational runner and geek.

Read full bio
UI_Icon-Red_Hat-Close-A-Black-RGB

Browse by channel

automation icon

Automation

The latest on IT automation for tech, teams, and environments

AI icon

Artificial intelligence

Updates on the platforms that free customers to run AI workloads anywhere

open hybrid cloud icon

Open hybrid cloud

Explore how we build a more flexible future with hybrid cloud

security icon

Security

The latest on how we reduce risks across environments and technologies

edge icon

Edge computing

Updates on the platforms that simplify operations at the edge

Infrastructure icon

Infrastructure

The latest on the world’s leading enterprise Linux platform

application development icon

Applications

Inside our solutions to the toughest application challenges

Original series icon

Original shows

Entertaining stories from the makers and leaders in enterprise tech