• Uncategorized

About java : How-can-I-find-out-what-version-of-Log4J-I-am-using

Question Detail

As we all know, at least four or five Log4j JAR files end up being in the classpath. How can I tell which version I am using?

Question Answer

I came here after learning my servers may be vulnerable to the new Log4j exploit (CVE-2021-44228). So I needed to know whether I had an outdated/vulnerable build of Log4j version 2 installed.

Previous answers here do not help with detecting old versions, because they are for letting already-running Java code figure out which version of Log4j that code uses, whereas I need to know if any Java app could be using a vulnerable version.

Here’s what I did instead:

sudo find / -name 'log4j*'

This lists all Log4j related files on my (Linux) server. That showed me a few 1.x versions, which are not vulnerable to this specific CVE, and one 2.15.0 file, which already contains the fix for the CVE.

If you run this and find file or folder names that have 2.x, where x < 15, then you are likely vulnerable, and need to figure out how to update your files ASAP.

Caution

I was warned that this is not enough of a test for my purpose because the Log4j files may be hidden inside a .jar file, which the find command would not discover.

Update

Here’s a public project that attempts to scan all .jar files, in order to find Log4j code inside archives as well: Log4-detector

It depends on the ClassLoader, but have a look at the example:

import org.apache.log4j.Layout;

public class X {
    public static void main(String[] a) {
        Package p = Layout.class.getPackage();
        System.out.println(p);
        System.out.println("Implementation title:   " + p.getImplementationTitle());
        System.out.println("Implementation vendor:  " + p.getImplementationVendor());
        System.out.println("Implementation version: " + p.getImplementationVersion());
    }
}

You can call the method getImplementationVersion on the Layout class of log4j:

org.apache.log4j.Layout.class.getPackage().getImplementationVersion()

I wouldn’t expect this to be the preferred method, but it is how I determined the version of Log4j that my software was using:

Open, or extract the contents of, the Log4j .jar using a .zip archiving utility (Windows Explorer supports this). Navigate into the “META-INF” sub-directory and open the file “MANIFEST.MF” in a text editor. Find the line starting with “Implementation-Version“, this is the Log4j version.

Obviously, this is not a programmatic solution. But if you simply want to know what version you are using and you have the .jar archive, it works.

I noticed that Package.getSpecificationVersion() and Package.getImplementationVersion(), as mentioned in Loic M.’s answer, work for other .jar libraries, but not my Log4j. It’s possible that the version I am using just doesn’t support it.

I downloaded version 2.13.1 to try out the above mentioned methods and found that they do work with it. So it was my version (1.2.16) that didn’t support them and returned null.

To know the Log4j version during runtime in Java:

LOGGER.info("Log4j version: " + org.apache.logging.log4j.util.PropertiesUtil.class.getPackage().getImplementationVersion());

Or

System.out.println("Log4j version: " + org.apache.logging.log4j.util.PropertiesUtil.class.getPackage().getImplementationVersion());

Delete all the JAR files of the versions you don’t need (one should be enough) and to find out the version of the one that’s left, look at the filename.

For example:

log4j-1.2.17.jar

I’ve written a small Bash script to check versions of each Log4j JAR file located on that server. It reads the version information from the manifest file, since trusting in file names is a little risky.

locs=( $(sudo find / -name 'log4j*'|grep jar) )
fcount=${#locs[@]}

echo "Found $fcount jar files"
echo " "

for (( j=0; j<${fcount}; j++ ));
do
    unzip ${locs[$j]} META-INF/MANIFEST.MF
    mv META-INF/MANIFEST.MF META-INF/MANIFEST$j.MF
done

echo " "
for (( j=0; j<${fcount}; j++ ));
do
    echo ${locs[$j]}
    tail -2 META-INF/MANIFEST$j.MF
done

  1. Because there are multiple versions of same classes from different Log4j dependencies, any of them could get loaded during runtime (given that same class name is present in different JAR files).

  2. I use plugins provided by Eclipse and IntelliJ IDEA to see the Maven dependency tree. Then I exclude the older ones to have only the needed Log4j version.

Look inside the core.jar -> log4j-core .zip\META-INF\maven\org.apache.logging.log4j\log4j-core\pom files shows the version

An easy way to do this:

  1. Put a debug breakpoint at log.debug()
  2. Step ‘into’ next statement to determine the class which is called.
  3. Check the JAR version of the called class.

Bearing in mind the Log4j 2 Security Vulnerability CVE-2021-45105:
On Linux and macOS you can use Syft to generate a software bill of materials (SBOM) and Grype to scan for vulnerabilities. Used in combination, you can find where risky versions of Log4j exist, which versions you have and get a report on the vulnerabilities.

Apache recommend ditching Log4j 1, and at least use their ‘bridge’, log4j-1.2-api, to call Log4j 2 from applications which contain 1.x calls.

You may also like...

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.