Skip to content
KitploitKITPLOIT
StrumentiBlog
Invia
StrumentiBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
log4shell-example — L'obiettivo di questo progetto è dimostrare la vulnerabilità di exploit log4j cve-2021-44228 in una configurazione spring-boot e mostrare come correggerla. | Kitploit
Strumenti/GitHubGitHub/chilit-nl/log4shell-example
Analisi delle VulnerabilitàAnalisi del CodiceExploitSicurezza WebApprendimento e FormazioneLab e Pratica
GitHubchilit-nl/log4shell-example

log4shell-example

L'obiettivo di questo progetto è dimostrare la vulnerabilità di exploit log4j cve-2021-44228 in una configurazione spring-boot e mostrare come correggerla.

Vedi Repository
24 anni faNon ancora revisionato

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi

Test dell'Exploit Log4Shell

L'obiettivo di questo progetto è dimostrare la vulnerabilità di exploitation di log4j cve-2021-44228 in un ambiente spring-boot e mostrare come risolverla.

Questo progetto contiene tre sottomoduli. Uno di questi contiene codice vulnerabile, gli altri due sono corretti (patched).

Come usare questo progetto

Esegui ./mvnw clean test nella radice del progetto per lanciare i test in entrambi i moduli. In log4shell-example-unpatched, vedrai molte eccezioni (il test passerà comunque, perché è previsto), poiché non riceve la risposta corretta dal server a cui tenta di connettersi.

Quando sono vulnerabile?

La tua applicazione è vulnerabile se hai sovrascritto il logger predefinito, in modo che utilizzi l'implementazione log4j2, e non hai sovrascritto la versione di log4j2 utilizzata. Il pom sarà simile a questo:```xml org.springframework.boot spring-boot-starter org.springframework.boot spring-boot-starter-logging

root@kitploit:~
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
root@kitploit:~
Puoi vedere che le tue invocazioni di log sono ora vulnerabili eseguendo il test in `log4shell-example-unpatched`. Questo test ha successo quando le invocazioni di log sono vulnerabili.

### Utilizzare il test di integrazione Spring per verificare se la tua applicazione è vulnerabile

#### 1. Aggiungi il `Log4ShellTest` al tuo progetto

Aggiungi il `Log4ShellTest` da `log4shell-example-patched-version` al tuo progetto:```java
import lombok.extern.log4j.Log4j2;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;

@SpringBootTest
@Import(Log4ShellTest.Log4ShellConfig.class)
public class Log4ShellTest {

    @Autowired
    private List<Log4ShellService> servicesToTest;

    @Test
    public void testVulnerabilityPatched() throws Exception {

        CountDownLatch waitLatch = new CountDownLatch(1);
        AtomicInteger connectionAttemptCounter = new AtomicInteger();
        Thread listener = new Thread(() -> {
            try {
                ServerSocket socket = new ServerSocket(22345);
                while(true) {
                    waitLatch.countDown();
                    Socket connection = socket.accept();
                    connectionAttemptCounter.getAndIncrement();
                    connection.close();
                }
            }
            catch(IOException ex) {
                throw new IllegalStateException(ex);
            }
        });
        listener.start();
        waitLatch.await();

        servicesToTest.forEach(service -> service.testLog("${jndi:ldap://127.0.0.1:22345}"));

        Assertions.assertEquals(0, connectionAttemptCounter.get());
        // If you're not using lombok, change the 6 to 2
        Assertions.assertEquals(6, servicesToTest.size());

        listener.interrupt();

    }

    @Configuration
    @ComponentScan
    public static class Log4ShellConfig {

    }

    public interface Log4ShellService {
        void testLog(String arg);
    }

    @Component
    public static class Service1 implements Log4ShellService {

        private static final Logger logger = LogManager.getLogger("Test");

        @Override
        public void testLog(String arg) {
            logger.info("Test: " + arg);
        }
    }

    @Component
    public static class Service2 implements Log4ShellService {

        private static final Logger logger = LogManager.getLogger("Test");

        @Override
        public void testLog(String arg) {
            logger.info("Test: {}", arg);
        }
    }

    // Remove this class if you're not using lombok
    @Component
    @Slf4j
    public static class Service3 implements Log4ShellService {

        @Override
        public void testLog(String arg) {
            log.info("Test: {}", arg);
        }
    }

    // Remove this class if you're not using lombok
    @Component
    @Slf4j
    public static class Service4 implements Log4ShellService {

        @Override
        public void testLog(String arg) {
            log.info("Test: " + arg);
        }
    }

    // Remove this class if you're not using lombok
    @Component
    @Log4j2
    public static class Service5 implements Log4ShellService {

        @Override
        public void testLog(String arg) {
            log.info("Test: {}", arg);
        }
    }

    // Remove this class if you're not using lombok
    @Component
    @Log4j2
    public static class Service6 implements Log4ShellService {

        @Override
        public void testLog(String arg) {
            log.info("Test: " + arg);
        }
    }

}

2. Verifica che questo test fallisca

Esegui il test e verifica che fallisca. Se non fallisce, dovresti vedere le seguenti righe di log e non sei vulnerabile:``` 2021-12-13 22:05:01.197 INFO 21216 --- [ main] Test : Test: ${jndi:ldap://127.0.0.1:22345} 2021-12-13 22:05:01.198 INFO 21216 --- [ main] Test : Test: ${jndi:ldap://127.0.0.1:22345} 2021-12-13 22:05:01.199 INFO 21216 --- [ main] n.c.l.Log4ShellTest$Service3 : Test: ${jndi:ldap://127.0.0.1:22345} 2021-12-13 22:05:01.199 INFO 21216 --- [ main] n.c.l.Log4ShellTest$Service4 : Test: ${jndi:ldap://127.0.0.1:22345} 2021-12-13 22:05:01.199 INFO 21216 --- [ main] n.c.l.L.Service5 : Test: ${jndi:ldap://127.0.0.1:22345} 2021-12-13 22:05:01.199 INFO 21216 --- [ main] n.c.l.L.Service6 : Test: ${jndi:ldap://127.0.0.1:22345}

root@kitploit:~
Se il test fallisce, dovresti vedere uno stack trace che dice che una connessione è chiusa:```
2021-12-13 22:06:50,635 main WARN Error looking up JNDI resource [ldap://127.0.0.1:22345]. javax.naming.CommunicationException: anonymous bind failed: 127.0.0.1:22345 [Root exception is java.net.SocketException: Socket closed]
	at java.naming/com.sun.jndi.ldap.LdapClient.authenticate(LdapClient.java:198)
	at java.naming/com.sun.jndi.ldap.LdapCtx.connect(LdapCtx.java:2895)
	at java.naming/com.sun.jndi.ldap.LdapCtx.<init>(LdapCtx.java:348)
	at java.naming/com.sun.jndi.url.ldap.ldapURLContextFactory.getUsingURLIgnoreRootDN(ldapURLContextFactory.java:60)
	at java.naming/com.sun.jndi.url.ldap.ldapURLContext.getRootURLContext(ldapURLContext.java:61)
	at java.naming/com.sun.jndi.toolkit.url.GenericURLContext.lookup(GenericURLContext.java:204)
	at java.naming/com.sun.jndi.url.ldap.ldapURLContext.lookup(ldapURLContext.java:94)
	at java.naming/javax.naming.InitialContext.lookup(InitialContext.java:409)
	at org.apache.logging.log4j.core.net.JndiManager.lookup(JndiManager.java:172)
	at org.apache.logging.log4j.core.lookup.JndiLookup.lookup(JndiLookup.java:56)
	at org.apache.logging.log4j.core.lookup.Interpolator.lookup(Interpolator.java:221)
	at org.apache.logging.log4j.core.lookup.StrSubstitutor.resolveVariable(StrSubstitutor.java:1110)
	at org.apache.logging.log4j.core.lookup.StrSubstitutor.substitute(StrSubstitutor.java:1033)
	at org.apache.logging.log4j.core.lookup.StrSubstitutor.substitute(StrSubstitutor.java:912)
	at org.apache.logging.log4j.core.lookup.StrSubstitutor.replace(StrSubstitutor.java:467)
	at org.apache.logging.log4j.core.pattern.MessagePatternConverter.format(MessagePatternConverter.java:132)
	at org.apache.logging.log4j.core.pattern.PatternFormatter.format(PatternFormatter.java:38)
	at org.apache.logging.log4j.core.layout.PatternLayout$PatternSerializer.toSerializable(PatternLayout.java:344)
	at org.apache.logging.log4j.core.layout.PatternLayout.toText(PatternLayout.java:244)
	at org.apache.logging.log4j.core.layout.PatternLayout.encode(PatternLayout.java:229)
	at org.apache.logging.log4j.core.layout.PatternLayout.encode(PatternLayout.java:59)
	at org.apache.logging.log4j.core.appender.AbstractOutputStreamAppender.directEncodeEvent(AbstractOutputStreamAppender.java:197)
	at org.apache.logging.log4j.core.appender.AbstractOutputStreamAppender.tryAppend(AbstractOutputStreamAppender.java:190)
	at org.apache.logging.log4j.core.appender.AbstractOutputStreamAppender.append(AbstractOutputStreamAppender.java:181)
	at org.apache.logging.log4j.core.config.AppenderControl.tryCallAppender(AppenderControl.java:156)
	at org.apache.logging.log4j.core.config.AppenderControl.callAppender0(AppenderControl.java:129)
	at org.apache.logging.log4j.core.config.AppenderControl.callAppenderPreventRecursion(AppenderControl.java:120)
	at org.apache.logging.log4j.core.config.AppenderControl.callAppender(AppenderControl.java:84)
	at org.apache.logging.log4j.core.config.LoggerConfig.callAppenders(LoggerConfig.java:540)
	at org.apache.logging.log4j.core.config.LoggerConfig.processLogEvent(LoggerConfig.java:498)
	at org.apache.logging.log4j.core.config.LoggerConfig.log(LoggerConfig.java:481)
	at org.apache.logging.log4j.core.config.LoggerConfig.log(LoggerConfig.java:456)
	at org.apache.logging.log4j.core.config.AwaitCompletionReliabilityStrategy.log(AwaitCompletionReliabilityStrategy.java:82)
	at org.apache.logging.log4j.core.Logger.log(Logger.java:161)
	at org.apache.logging.log4j.spi.AbstractLogger.tryLogMessage(AbstractLogger.java:2205)
	at org.apache.logging.log4j.spi.AbstractLogger.logMessageTrackRecursion(AbstractLogger.java:2159)
	at org.apache.logging.log4j.spi.AbstractLogger.logMessageSafely(AbstractLogger.java:2142)
	at org.apache.logging.log4j.spi.AbstractLogger.logMessage(AbstractLogger.java:2017)
	at org.apache.logging.log4j.spi.AbstractLogger.logIfEnabled(AbstractLogger.java:1983)
	at org.apache.logging.log4j.spi.AbstractLogger.info(AbstractLogger.java:1320)
	at nl.chilit.log4shellexampleunpatched.Log4ShellTest$Service1.testLog(Log4ShellTest.java:78)
	at nl.chilit.log4shellexampleunpatched.Log4ShellTest.lambda$testVulnerabilityNotPatched$1(Log4ShellTest.java:52)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
	at nl.chilit.log4shellexampleunpatched.Log4ShellTest.testVulnerabilityNotPatched(Log4ShellTest.java:52)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:78)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:567)
	at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:725)
	at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
	at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
	at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
	at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
	at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
	at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
	at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
	at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:214)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:210)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:135)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:66)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
	at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
	at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53)
	at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:71)
	at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
	at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)
	at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)
Caused by: java.net.SocketException: Socket closed
	at java.base/sun.nio.ch.NioSocketImpl.ensureOpenAndConnected(NioSocketImpl.java:165)
	at java.base/sun.nio.ch.NioSocketImpl.beginWrite(NioSocketImpl.java:366)
	at java.base/sun.nio.ch.NioSocketImpl.implWrite(NioSocketImpl.java:411)
	at java.base/sun.nio.ch.NioSocketImpl.write(NioSocketImpl.java:440)
	at java.base/sun.nio.ch.NioSocketImpl$2.write(NioSocketImpl.java:826)
	at java.base/java.net.Socket$SocketOutputStream.write(Socket.java:1045)
	at java.base/java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:81)
	at java.base/java.io.BufferedOutputStream.flush(BufferedOutputStream.java:142)
	at java.naming/com.sun.jndi.ldap.Connection.writeRequest(Connection.java:414)
	at java.naming/com.sun.jndi.ldap.Connection.writeRequest(Connection.java:387)
	at java.naming/com.sun.jndi.ldap.LdapClient.ldapBind(LdapClient.java:359)
	at java.naming/com.sun.jndi.ldap.LdapClient.authenticate(LdapClient.java:192)
	... 110 more

3. Applica la patch alla tua applicazione

Applica la patch alla tua applicazione in uno dei modi descritti di seguito, ed esegui nuovamente il test. Il test ora dovrebbe essere verde.

Mitigare la vulnerabilità

Puoi mitigare la vulnerabilità in alcuni modi, come dimostrato in log4shell-example-patched-system-property e log4shell-example-patched-version.

Mitigazione tramite l'aggiornamento della versione (metodo migliore)

Se la configurazione della tua applicazione lo consente, il metodo migliore per eliminare la vulnerabilità è aggiornare la versione di logj4 ad almeno 2.15. Puoi farlo impostando log4j2.version su 2.15.0:```xml <log4j2.version>2.15.0</log4j2.version>

root@kitploit:~
Questa soluzione funziona solo *quando stai usando l'artifact spring-boot-parent da qualche parte nella tua catena come parent*. Se stai usando `dependencyManagement` per gestire le tue dipendenze spring-boot, questa soluzione non funzionerà per te:```xml
    <!-- if you are using dependency management like this, upping the version by setting log4j2.version is NOT going to work -->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.6.1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

In tal caso, dovrai sovrascrivere le versioni per ogni componente di log4j, e la cosa diventa rapidamente complicata.

Mitigazione tramite l'impostazione di una proprietà di sistema

NOTA: questa correzione funziona SOLO per versioni di log4j >= 2.10

Puoi anche mitigare il problema impostando la proprietà di sistema log4j2.formatMsgNoLookups su true. NOTA BENE: NON puoi impostarla in application.properties o application.yml. Devi:

  • impostarla tramite riga di comando (aggiungendo -Dlog4j2.formatMsgNoLookups=true al comando java per avviare il servizio)
  • oppure come variabile d'ambiente (impostando LOG4J_FORMAT_MSG_NO_LOOKUPS su true) nell'ambiente in cui l'applicazione è in esecuzione
  • oppure, come dimostrato in log4shell-example-patched-system-property, impostando una proprietà di sistema ancor prima che spring boot sia avviato (prima di chiamare SpringApplication.run(...))

L'ultima soluzione è implementata sia in Log4JMitigationExtension che in Log4JMitigationExtension. Poiché il test di integrazione non usa il metodo main di Log4JMitigationExtension, viene usata un'estensione per impostare la proprietà in tempo utile affinché log4j la rilevi.

Scarica lo strumento