← back
CVE-2021-45105mediumobserved exploitationCWE-20CWE-674

Apache Log4j2 does not always protect from infinite recursion in lookup evaluation

77Vexday Risk Score

Prioritize patching. It exploitation observed by VulnCheck and has a public proof of concept.

ssvc Actcvss 5.9epss 100%
from disclosure to weapon4 days
Published on NVDDec 18
1st PoC+4d
VulnCheck+4d
exploitation probability
100%top 1% of all CVEs
observed exploitation
yesVulnCheck
1 public exploit(s)

Summary

DoS por recursão descontrolada (CWE-674/CWE-835) no processamento de lookups do Log4j2. Ao contrário do Log4Shell (CVE-2021-44228), não leva a RCE: um atacante que controle dados do Thread Context Map (MDC) e uma configuração de logging não padrão pode provocar StackOverflowError e derrubar o processo. O EPSS próximo de 1.0 reflete a onda de varredura em massa da família Log4j, não a facilidade real desta falha específica, que exige pré-condições que a maioria dos ambientes não tem.

Technical detail

A falha está na classe StrSubstitutor do Log4j2, responsável pela substituição de variáveis em lookups. Quando uma variável aninhada é substituída, o método substitute() é chamado recursivamente. O problema surge quando a variável aninhada referencia a própria variável sendo substituída: a recursão é chamada repetidamente com a mesma string, sem terminar. Segundo a análise da Zero Day Initiative (equipe da Trend Micro), quando uma variável aninhada é substituída pela classe StrSubstitutor, ela chama recursivamente substitute(); porém, quando a variável aninhada referencia a variável sendo substituída, a recursão é chamada com a mesma string, levando a recursão infinita e uma condição de DoS no servidor.

O resultado prático é um StackOverflowError que encerra o processo. É importante entender que esta vulnerabilidade não deve ser considerada uma variante do Log4Shell (CVE-2021-44228), embora abuse de vetor de ataque similar: ambas abusam de lookups controlados pelo atacante em dados logados, mas neste caso lookups não-JNDI podem ser abusados. Ou seja, o vetor de entrada (dados atacante-controlados que chegam ao mecanismo de lookup) é o mesmo do Log4Shell, mas a consequência é indisponibilidade, não execução de código.

O NVD classifica a falha sob CWE-20 (validação imprópria de entrada) e CWE-674 (recursão descontrolada); outras bases usam CWE-835 (loop com condição de saída inatingível). Todas descrevem o mesmo defeito: o produto não controla adequadamente a quantidade de recursão que ocorre, consumindo recursos excessivos como memória alocada ou a pilha do programa.

Apenas o componente log4j-core é afetado. Somente o pacote org.apache.logging.log4j:log4j-core é diretamente afetado por esta vulnerabilidade; o log4j-api deve ser mantido na mesma versão do log4j-core para garantir compatibilidade, se estiver em uso.

How it’s exploited

A pré-condição decisiva — frequentemente omitida das manchetes — é a configuração de logging. Um Pattern Layout não padrão na configuração de logging é necessário para acionar a CVE-2021-45105. Concretamente, quando a configuração de logging usa um Pattern Layout não padrão com um Context Lookup (por exemplo, $${ctx:loginId}), atacantes com controle sobre os dados de entrada do Thread Context Map (MDC) podem criar entrada maliciosa contendo um lookup recursivo, resultando em um StackOverflowError que encerra o processo — um ataque de negação de serviço.

O fluxo de exploração demonstrado pela ZDI ilustra os pré-requisitos concretos: a aplicação de exemplo é configurada com um Pattern Layout customizado contendo um Context Lookup (${ctx:apiversion}); implementa um servidor HTTP e define o valor do cabeçalho X-Api-Version recebido como o valor da variável apiversion no Thread Context Map. Sem essa combinação — Context Lookup presente no pattern E um campo do MDC alimentado por entrada externa — não há gatilho. Ambientes com a configuração padrão do Log4j2 não são exploráveis por este caminho.

O impacto final é estritamente disponibilidade: derrubar o processo Java com StackOverflowError. O vetor CVSS AV:N/AC:H reflete isso — rede, mas complexidade alta, sem impacto em confidencialidade ou integridade. O EPSS de ~1.0 deve ser lido com ceticismo: ele é inflado pela varredura indiscriminada por strings `${...}` que caracterizou a crise Log4j em dezembro de 2021, quando qualquer sonda pode aparecer nos mesmos logs. A exploração dirigida desta CVE específica requer conhecimento da configuração-alvo e de qual campo do MDC é atacante-controlável.

Versions

Affected
Apache Log4j2 2.0-alpha1 até 2.16.0, excluindo 2.12.3 e 2.3.1. Somente o artefato log4j-core. Log4j 1.x não é afetado.
Fixed in
2.17.0 (ramo Java 8+), 2.12.3 (backport Java 7) e 2.3.1 (backport Java 6).

How to protect

A correção é atualizar o log4j-core. O problema foi corrigido no Log4j 2.17.0, 2.12.3 e 2.3.1. Usuários de Java 8 (ou posterior) devem atualizar para a release 2.17.0; 2.12.3 é o backport para o ramo Java 7 e 2.3.1 para o ramo Java 6. Na 2.17.0 a raiz foi eliminada arquiteturalmente: foram criadas duas classes que herdam de StrSubstitutor — ConfigurationStrSubstitutor, que só interpreta substituições em parâmetros de configuração, e RuntimeStrSubstitutor, que interpreta strings que podem conter entrada do usuário; com RuntimeStrSubstitutor, nenhuma avaliação recursiva é permitida.

Se a atualização não for imediata, há paliativos de configuração que atacam o pré-requisito, não a raiz. Segundo o advisory da Apache: alternativamente, isso pode ser mitigado na configuração — no PatternLayout, substitua Context Lookups como ${ctx:loginId} ou $${ctx:loginId} por padrões do Thread Context Map (%X, %mdc ou %MDC); caso contrário, remova referências a Context Lookups onde elas se originam de fontes externas à aplicação, como cabeçalhos HTTP ou entrada do usuário. O custo é operacional: exige inventariar cada configuração de logging e revisar cada uso de Context Lookup, o que em ambientes grandes é mais trabalhoso que o upgrade.

Sobre mitos: as mitigações amplamente divulgadas para o Log4Shell — remover a classe JndiLookup ou setar `log4j2.formatMsgNoLookups=true` — NÃO endereçam esta CVE, pois o abuso aqui é de lookups não-JNDI e não passa pela formatação de mensagem. Além disso, atualizar apenas para 2.16.0 é insuficiente: a 2.16.0 corrigiu CVE-2021-44228/45046 mas ainda contém este defeito. Log4j 1.x não é afetado por esta falha (mas está fora de suporte e tem outros problemas).

How to detect

Não há assinatura de rede confiável específica desta CVE. O gatilho é uma string com lookup auto-referencial chegando por um campo que alimenta o MDC (ex.: cabeçalho HTTP), e à primeira vista se parece com o tráfego de varredura genérico da família Log4j — as próprias assinaturas de IPS de fornecedores para este período detectavam o padrão amplo de exploração Log4j, não este DoS em particular. O sinal mais confiável é do lado do host, não da rede.

O indicador de exploração bem-sucedida é a terminação do processo Java por java.lang.StackOverflowError com stack traces mostrando chamadas recursivas repetidas a org.apache.logging.log4j...StrSubstitutor.substitute. Procure por crashes/reinícios inesperados de JVMs correlacionados com entrada externa incomum em campos que sabidamente alimentam o Thread Context Map. Ausência desse StackOverflowError nos logs, combinada com configuração de PatternLayout sem Context Lookups externos, é forte evidência de que o ambiente não é explorável por este vetor.

Researched and written with AI from the vendor advisory and public analysis, with the sources above. Always confirm the fixed version in the official advisory before acting.
Apache Log4j2 versions 2.0-alpha1 through 2.16.0 (excluding 2.12.3 and 2.3.1) did not protect from uncontrolled recursion from self-referential lookups. This allows an attacker with control over Thread Context Map data to cause a denial of service when a crafted string is interpreted. This issue was fixed in Log4j 2.17.0, 2.12.3, and 2.3.1.
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:H
⚠ Public resources, to assess the exposure of systems you control or are authorized to test. Test only with authorization.