
Uma correção baseada no agente Java Byte Buddy para o CVE-2021-44228, a vulnerabilidade "JNDI LDAP" do log4j 2.x.
Um fix baseado em agente Java Byte Buddy para CVE-2021-44228, a vulnerabilidade "JNDI LDAP" do log4j 2.x.
Ele faz três coisas:
jndi: ("lookups").System.err (ou seja, stderr) indicando que uma tentativa JNDI do log4j foi feita (incluindo a string de formato tentada, com quaisquer caracteres ${} sanitizados para evitar injeções transitivas)."(log4j jndi disabled)" na mensagem de log (para evitar injeções transitivas).Adicione -javaagent:path/to/log4j-jndi-be-gone-1.0.0-standalone.jar aos seus comandos java.
Nota: Se você já tem Byte Buddy no classpath, tente usar log4j-jndi-be-gone-1.0.0.jar.
$ java -javaagent:path/to/log4j-jndi-be-gone-1.0.0-standalone.jar -jar path/to/some.jar
A partir da versão 1.1.0, log4j-jndi-be-gone padrão tenta lidar com versões reempacotadas (também chamadas de "shaded") do log4j que podem estar incorporadas em um JAR sob um nome de pacote alternativo para evitar colisões entre a versão de uma dependência da aplicação e a versão da mesma dependência de uma dependência. No entanto, deve-se notar que log4j parece não ser facilmente reempacotado sob nomes/prefixos de pacote alternativos devido ao uso de reflexão com nomes de classe estáticos e/ou nomes de classe de arquivos de configuração incorporados.
Esse comportamento pode ser desabilitado colocando =structureMatch=0 após o caminho do JAR do agente no argumento -javaagent:, por exemplo:
-javaagent:path/to/log4j-jndi-be-gone-1.0.0-standalone.jar=structureMatch=0
o que resultará no mesmo comportamento de correspondência do 1.0.0, uma simples comparação exata de string contra o nome da classe.
Você pode construir o JAR com ./gradlew (build/libs/log4j-jndi-be-gone-1.0.0(-standalone).jar) ou obtê-lo na página de releases.
O JAR do agente log4j-jndi-be-gone suporta Java 6-17+.
A implementação começa por corresponder classes com sufixos que correspondem aos sub-pacotes mais internos e ao nome de classe de org.apache.logging.log4j.core.lookup.JndiLookup, lookup.JndiLookup, já que org.apache.logging.log4j.core pode razoavelmente ser esperado ter sido distorcido por regras de reempacotamento que não buscaram preservar nomes de pacotes. Além disso, em vez de apenas realizar verificações similares para todos os outros tipos esperados do log4j, garante que eles também existam sob o mesmo pacote base.
A implementação então percorre a estrutura de qualquer classe log4j lookup.JndiLookup potencial identificada, tentando validar contra:
org.apache.logging.log4j.core.config.plugins.Plugin esperada em todas as versões 2.x, incluindo parâmetros da anotação e seus valoreslookup(), correspondendo seus modificadores e assinatura de tipo (e ignorando a versão de 1 argumento do 2.0)convertJndiName(), correspondendo seus modificadores e assinatura de tipoCONTAINER_JNDI_RESOURCE_PATH_PREFIX, correspondendo seus modificadoreslog4j-jndi-be-gone não funcionará se a biblioteca log4j tiver sido ofuscada ou se seus pacotes/nomes de classe tiverem sido modificados além do reempacotamento básico (ou seja, "shading").
log4j-jndi-be-gone-1.0.0-standalone.jar empacota o Byte Buddy. Se você já usa Byte Buddy, pode encontrar problemas com ele. Tente usar A partir da versão 1.1.0, o JAR standalone do log4j-jndi-be-gone empacota um Byte Buddy reempacotado sob seu próprio prefixo de pacote. Isso deve evitar quaisquer colisões.log4j-jndi-be-gone-1.0.0.jar em vez disso, embora note que log4j-jndi-be-gone espera Byte Buddy 1.12.x.
Se você substituiu suas classes JndiLookup por implementações que tentam fazer honeypotting ou registrar chamadas lookup(), log4j-jndi-be-gone irá potencialmente desabilitar o método lookup delas, impedindo seu funcionamento.
O diretório tests/jnditest contém um caso de teste simples onde uma chamada de log do log4j passa uma string de formato JNDI LDAP. Ele também configura seu próprio ouvinte de porta para determinar se uma tentativa de conexão foi feita pelo log4j e falha no teste se uma conexão for recebida.
$ ./tests/jnditest/test-uninstrumented.sh
BUILD SUCCESSFUL in 1s
6 actionable tasks: 5 executed, 1 up-to-date
BUILD SUCCESSFUL in 1s
3 actionable tasks: 3 up-to-date
JUnit version 4.12
.16:08:49.547 [main] ERROR trust.nccgroup.jnditest.test.JndiTest - Hello, _${jndi:ldap://127.0.0.1:8899/evil}_!
E
Time: 0.929
There was 1 failure:
1) logging(trust.nccgroup.jnditest.test.JndiTest)
java.lang.AssertionError: jndi ldap connection received
at org.junit.Assert.fail(Assert.java:88)
at trust.nccgroup.jnditest.test.JndiTest.logging(JndiTest.java:55)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runners.Suite.runChild(Suite.java:128)
at org.junit.runners.Suite.runChild(Suite.java:27)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runners.Suite.runChild(Suite.java:128)
at org.junit.runners.Suite.runChild(Suite.java:27)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
at org.junit.runner.JUnitCore.runMain(JUnitCore.java:77)
at org.junit.runner.JUnitCore.main(JUnitCore.java:36)
at trust.nccgroup.jnditest.Main.main(Main.java:24)
FAILURES!!!
Tests run: 1, Failures: 1
$ ./tests/jnditest/test-instrumented.sh
BUILD SUCCESSFUL in 1s
6 actionable tasks: 5 executed, 1 up-to-date
BUILD SUCCESSFUL in 1s
3 actionable tasks: 3 up-to-date
JUnit version 4.12
.log4j jndi lookup attempted: (sanitized) ldap://127.0.0.1:8899/evil
16:09:06.064 [main] ERROR trust.nccgroup.jnditest.test.JndiTest - Hello, _(log4j jndi disabled)_!
Time: 1.362
OK (1 test)
Licenciado sob a licença Apache 2.
log4j-jndi-be-gone foi testado no OpenJDK 6, 8, 11 e 17, e nas JVMs HotSpot e OpenJ9.