Regarding the log4j2 vulnerability, CVE-2021-44228

On the 9th of December, a remote code execution exploit CVE-2021-44228 was discovered in a popular Java logging library called log4j2. A good write-up of this vulnerability can be found here:

As a user of Lightbend technologies, you may or may not be affected by this vulnerability.

Lightbend, in all of our libraries, uses SLF4J for logging. SLF4J isn’t a logging library itself, rather, it is an abstraction over logging libraries, with almost ubiquitous use across the Java ecosystem by open source libraries. It allows open source libraries to log without forcing a particular logging library onto their users.

Log4j2 is one implementation of SLF4J, and perhaps the most popular implementation. Lightbend however has always recommended using a different implementation called logback. Logback is not vulnerable to the log4j2 vulnerability, hence, if you have decided to use logback in your projects with Lightbend’s technologies, you will not be vulnerable to the log4j2 vulnerability.

Nevertheless, Lightbend does not force you to use logback, and in some cases we provide instructions, examples, libraries and sample code that assist in using log4j2. We therefore recommend that you audit all of your systems to identify whether log4j2 is in use.

How do I know whether I am using log4j2?

Typically, you can know if you are using log4j2 by checking your projects dependencies, which will be specified in your build.sbt, pom.xml or build.gradle files, depending on which build system you are using.

Build tool specific commands can help by listing all dependencies of a project, including transitive dependencies. In Maven, you can run mvn dependency:tree in each project. In the sbt shell, you can run show dependencyClasspathFiles on each project.

How can I fix the problem?

If you are using log4j2, the best fix is to upgrade to log4j2 2.15.0. This has been released with a fix for the vulnerability. If upgrading is not possible, then, if you are using log4j2 version 2.10.0 and above, you can set the log4j2.formatMsgNoLookups system property to true in your applications startup script, eg:

-Dlog4j2.formatMsgNoLookups=true

For versions from 2.7.0 onwards, you can also work around by changing your format patterns by replacing every instance of %m with %m{nolookups}.

Project specific considerations

Akka

Akka provides no built-in integration for any particular logging library, however the Akka documentation recommends using logback and only provides instructions for using logback.

Additionally, all of the Akka samples, such as those found here and in the Akka Platform Guide, use logback. Hence, if you have only followed the Akka documentation and/or Akka samples, you are most likely using logback.

Akka Serverless

The Akka Serverless Java and Scala SDKs have a hardcoded dependency on logback, making it impossible to use log4j2 without specific exclusions in your own project.

All Lightbend managed components of Akka Serverless have been audited to ensure only logback is in use.

Lagom Framework

By default, Lagom uses logback, however, we do provide instructions for using log4j2 instead, and we provide a library to assist with that. If you have selected to use log4j2, you will need to upgrade to log4j2 2.15.0. In maven, this can be done by adding the following to your root poms dependencyManagement section:

<dependency>
  <groupId>org.apache.logging.log4j</groupId>
  <artifactId>log4j-api</artifactId>
  <version>2.15.0</version>
</dependency>
<dependency>
  <groupId>org.apache.logging.log4j</groupId>
  <artifactId>log4j-core</artifactId>
  <version>2.15.0</version>
</dependency>
<dependency>
  <groupId>org.apache.logging.log4j</groupId>
  <artifactId>log4j-slf4j-impl</artifactId>
  <version>2.15.0</version>
</dependency>

This should appear after the Lagom bom dependency, to ensure it overrides the lagom bom. In sbt, this can be done by explicitly adding the correct log4j2 dependency to every project that uses it:

libraryDependencies ++= Seq(
  "org.apache.logging.log4j" % "log4j-slf4j-impl" % "2.15.0",
  "org.apache.logging.log4j" % "log4j-api" % "2.15.0",
  "org.apache.logging.log4j" % "log4j-core" % "2.15.0",
)

This upgrade has been tested with Lagom’s existing log4j2 support. Lightbend will, in the coming days, publish a new version of Lagom Framework for which the log4j2 support depends on 2.15.0.

Play Framework

By default, Play Framework uses logback, however, we do provide instructions for using log4j2. If you have followed those instructions, you will need to update your library dependencies to depend on log4j2 2.15.0:

libraryDependencies ++= Seq(
  "org.apache.logging.log4j" % "log4j-slf4j-impl" % "2.15.0",
  "org.apache.logging.log4j" % "log4j-api" % "2.15.0",
  "org.apache.logging.log4j" % "log4j-core" % "2.15.0",
)
3 Likes

Hello James

Thanks for sharing.

However, I would like to point out CVE-2019-17571 (critical severity) against log4j 1.2.17 that is used by lagom-scaladsl-kafka-broker (https://mvnrepository.com/artifact/com.lightbend.lagom/lagom-scaladsl-kafka-broker_2.13/1.6.5). Snyk scans of our projects that are using lagom 1.6.5 (latest version) are pointing this out as a critical severity.

Is there any workaround for this?

Regards
Manas

1 Like

Hello @manasbuilds . If it helps we use log4j-over-slf4j for some libraries that explicitly use log4j 1.x rather than slf4j and add exclusions.

CVE-2019-17571 with log4j 1.2.17 is now being addressed with the release of Lagom 1.6.7. Thanks to @octonato.

See here: Log4j 1.2.17 (CVE-2019-17571) critical vulnerability due to lagom-scala-dsl-kafka-broker - #5 by manasbuilds

Hi James,

Thank you for your guidance, specifically around sbt projects. I’d like to find dependencies on log4j in my project, however I’m finding show dependencyClasspath to be a bit difficult to use as-is. The reason is it prints the value of that setting using .toString(), which prints everything in that List on a single line at the console. It would be very convenient to grep the output if there was a way to print this setting using something like .foreach(println) instead. However I haven’t been able to figure out how to do this. Can you advise?

Thank you.

Michael

http://slf4j.org/log4shell.html

import sbt._

object Dependencies {
  object Versions {
    val slf4jV = "1.7.32"
    val logbackV = "1.2.8"
    val scalaLoggingV = "3.9.4"
  }
  val exclusions = Seq(
    ExclusionRule("log4j"),
    ExclusionRule("org.apache.logging.log4j"),
    ExclusionRule("commons-logging"),
    ExclusionRule("org.slf4j", "slf4j-api"),
  )
  val libraryDependencies = {
    import Versions._
    Seq(
      "ch.qos.logback"             %   "logback-core"    %  logbackV       % "compile",
      "ch.qos.logback"             %   "logback-classic" %  logbackV       % "compile",
      "com.typesafe.scala-logging" %%  "scala-logging"   %  scalaLoggingV  % "compile",
      // insert other deps
    ).map { _.excludeAll(exclusions: _*) } ++ Seq(
      "org.slf4j" % "log4j-over-slf4j" % slf4jV % "compile" force(),
      "org.slf4j" % "jcl-over-slf4j" % slf4jV % "compile" force(),
      "org.slf4j" % "slf4j-api" % slf4jV % "compile" force(),
    )
  }
}