【发布时间】:2016-09-23 03:32:13
【问题描述】:
众所周知,至少有四个或五个 Log4j JAR 文件最终位于类路径中。如何判断我使用的是哪个版本?
【问题讨论】:
众所周知,至少有四个或五个 Log4j JAR 文件最终位于类路径中。如何判断我使用的是哪个版本?
【问题讨论】:
删除所有不需要的版本的 JAR 文件(一个就足够了)并找出剩下的版本,查看文件名。
例如:
log4j-1.2.17.jar
【讨论】:
这取决于 ClassLoader,但看看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());
}
}
你可以在log4j的Layout类上调用getImplementationVersion方法:
org.apache.log4j.Layout.class.getPackage().getImplementationVersion()
【讨论】:
getImplementationVersion 和 getSpecificationVersion 方法可以使用它。对于旧版本,请参阅my answer below。
一个简单的方法:
【讨论】:
我不认为这是首选方法,但这是我确定我的软件使用的 Log4j 版本的方式:
使用 .zip 归档实用程序打开或提取 Log4j .jar 的内容(Windows Explorer 支持这一点)。导航到“META-INF”子目录并在文本编辑器中打开文件“MANIFEST.MF”。找到以“Implementation-Version”开头的那一行,这是Log4j版本。
显然,这不是程序化解决方案。但是,如果您只是想知道您使用的是什么版本并且您拥有 .jar 存档,那么它可以工作。
我注意到Package.getSpecificationVersion() 和Package.getImplementationVersion()(如Loic M.'s answer 中所述)适用于其他.jar 库,但不适用于我的Log4j。可能是我使用的版本不支持。
我下载了2.13.1 版本来尝试上面提到的方法,发现他们确实可以使用它。所以是我的版本(1.2.16)不支持它们并返回null。
【讨论】:
我在得知我的服务器可能容易受到新的 Log4j 漏洞利用 (CVE-2021-44228) 后来到这里。所以我需要知道我是否安装了过时/易受攻击的 Log4j 版本 2。
此处的先前答案无助于检测旧版本,因为它们是为了让已经运行的 Java 代码找出该代码使用的 Log4j 版本,而我需要知道是否有 any Java 应用程序可能正在使用易受攻击的版本。
这就是我所做的:
sudo find / -name 'log4j*'
这列出了我 (Linux) 服务器上所有与 Log4j 相关的文件。这向我展示了几个 1.x 版本,它们不易受到此特定 CVE 的攻击,还有一个 2.15.0 文件,其中已经包含 CVE 的修复程序。
如果您运行此程序并找到具有 2.x 的文件或文件夹名称,其中 x
我被警告说这不足以满足我的目的,因为 Log4j 文件可能隐藏在 .jar 文件中,find 命令不会发现该文件。
这是一个尝试扫描所有 .jar 文件的公共项目,以便在存档中也找到 Log4j 代码:Log4-detector
【讨论】:
for f in $(find / -name '*.jar' 2>/dev/null); do echo "Checking $f..."; unzip -l "$f" | grep -F org/apache/logging/log4j/core/lookup/JndiLookup.class; done
查看 core.jar -> log4j-core .zip\META-INF\maven\org.apache.logging.log4j\log4j-core\pom 文件显示版本
【讨论】:
我编写了一个小的 Bash 脚本来检查位于该服务器上的每个 Log4j JAR 文件的版本。它从清单文件中读取版本信息,因为信任文件名有点冒险。
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
【讨论】:
find 输出到达时对其进行循环,就可以避免数组出现的多个问题。简而言之,sudo find / -name 'log4j*.jar' -exec sh -c '... your loop code here ...' _ {} +
因为来自不同 Log4j 依赖项的相同类有多个版本,所以它们中的任何一个都可能在运行时加载(假设相同的类名存在于不同的 JAR 文件中)。
我使用Eclipse 和IntelliJ IDEA 提供的插件来查看Maven 依赖树。然后我排除旧版本,只使用所需的 Log4j 版本。
【讨论】:
Java 运行时了解 Log4j 版本:
LOGGER.info("Log4j version: " + org.apache.logging.log4j.util.PropertiesUtil.class.getPackage().getImplementationVersion());
或者
System.out.println("Log4j version: " + org.apache.logging.log4j.util.PropertiesUtil.class.getPackage().getImplementationVersion());
【讨论】: